Por que não podemos entender o conteúdo de um arquivo binário depois de compilado?

10

Até onde eu sei, todo programa consiste em um pacote de instruções do processador com algumas variáveis de dados específicas (float, int, char ...) para trabalhar no registradores do processador .

Então, a primeira coisa que pensei sobre isso (há muito tempo) é que, se você sabe que o valor ASCII de %¨#$¨# (apenas um exemplo aleatório) poderia ser interpretado como o endereço do stack pointer register (apenas exemplo) de um processador x86. Se isso for verdade, toda vez que você encontrar esse valor "ilegível" ao ler o conteúdo de um arquivo binário, poderá interpretar que o registro de ponteiro da pilha está sendo usado para gerenciar alguma variável de dados.

Infelizmente isso não acontece. Abaixo, há um exemplo do conteúdo do programa ping.exe do Windows aberto com notepad.exe :

Éumarquivobinárioeseusdadossãoincompreensíveisparanóssereshumanos(écompreensívelparamáquinas.)Nãofazqualquersentidoparaninguém,mesmoqueelessaibam Código de montagem (o nível mais baixo de linguagem de máquina.)

Então, se eu entendi tudo corretamente, alguém poderia explicar

  1. Por que um código binário não pode retornar ao código de montagem até onde estão, no fundo, a mesma coisa?
  2. Se alguém puder entender o código de montagem, por que o binário compilado resultante desse código "legível" não é mais?
por Diogo 15.03.2012 / 19:00

3 respostas

12

Primeiro, os registros não têm endereços. Cada instrução em qualquer linguagem assembly se traduz em um opcode. Opcodes no x86 podem ser um, dois, três ou até mais bytes (em alguns outros processadores eles são "largura fixa"). Normalmente, o opcode identifica a instrução, o modo de endereçamento e os registros envolvidos. O "modo de endereçamento" determina se é necessário mais do que o opcode pela CPU, ou seja, o modo de endereçamento "imediato" significa que há dados adicionais logo após (ou "imediatamente depois") a instrução para essa instrução - modos de endereçamento "absolutos" significa que endereço de memória segue a instrução e é usado por essa instrução.

Você pode descobrir o código de operação de algo como MOV AL,SP ou similar e pesquisá-lo. x86 tem muitas instruções que operam no ponteiro da pilha.

Mas por favor, por favor saia do Notepad e use um editor hexadecimal. Eu recomendaria HxD, embora existam muitos outros.

E @ David Schwartz está correto. Um desassemblador irá iterar através de um arquivo e converter opcodes novamente em texto legível. O que você quer fazer é totalmente possível.

No entanto, você precisa saber onde no arquivo as instruções começam porque se você começar no endereço errado, alguns dados que devem ser os "operandos" para os opcodes (como instruções que levam um endereço para um operando ou "argumento") pode ser mal interpretado como opcodes. Saber disso requer conhecimento do formato em que o executável está, que é para o Windows o formato "Portable Executable" ou PE (e geralmente é ELF para sistemas Linux). Tenho certeza de que há desmontadores que entendem PE, etc., mas eu não sei de nada.

    
por 15.03.2012 / 19:43
11

So, if I have understood everything correctly

Não é bem assim.

It is a binary file and its data is incomprehensible for us humans

Normalmente, um arquivo binário é incompreensível para humanos e máquinas, especialmente quando a finalidade do arquivo é desconhecida. Note que nem todos os arquivos binários são arquivos executáveis. Muitos arquivos binários são arquivos de dados que não contêm instruções de máquina. É por isso que as extensões de arquivo são usadas ao nomear arquivos (em alguns sistemas operacionais). A extensão. com foi usada pelo CP / M para denotar um arquivo executável. A extensão exe foi adicionada pelo MS-DOS para denotar outro formato de arquivo executável. * nixes usam o atributo execute para denotar quais arquivos podem ser executados, embora possam ser script e código.

Como já mencionado por outros, os arquivos binários, que contêm números, devem ser visualizados por um programa hexadecimal ou editor hexadecimal e não por um visualizador de texto.

there is a example of the content of the ping.exe program

Esse arquivo é, na verdade, um programa relocável, e nem todos os dados nesse arquivo representam o código da máquina. Há informações sobre o programa, como quais bibliotecas dinâmicas ele precisa, quais rotinas precisam ser vinculadas, requisitos para stack e program & memória de dados e ponto de entrada do programa. Os operandos de endereço no arquivo podem ser valores relativos que precisam ser calculados para valores absolutos ou referências que precisam ser resolvidas.

O "arquivo de programa" que você provavelmente está pensando é chamado de arquivo de imagem binária ou um despejo de memória de programa. Esse arquivo conteria apenas código de máquina e dados, com todas as referências de endereço configuradas corretamente para execução.

even if they know Assembly code(the lowest level of machine language.)

A linguagem de montagem não é o mesmo que a linguagem de máquina . O típico (como para excluir computadores de linguagem de alto nível) CPU aceita código de máquina como entrada, uma instrução de cada vez. Os operandos são registradores ou endereços de memória numéricos. A linguagem assembly é uma linguagem de nível mais alto que pode usar rótulos simbólicos para locais e variáveis de instrução, além de substituir os códigos operacionais numéricos por mnemônicos. Um programa de linguagem assembly tem que ser convertido para linguagem / código de máquina antes que ele possa realmente ser executado (normalmente por utilitários chamados assembler, linker e loader).

A operação inversa, desmontagem, pode ser executada em arquivos de programa com algum sucesso e perda de informações simbólicas. A desmontagem de um dump de memória ou arquivo de imagem de programa é mais trial & erro, pois os locais de código e dados precisam ser identificados manualmente.

BTW, existem pessoas que podem ler e codificar o código de máquina (numérico). É claro que isso é muito mais fácil em uma CPU de 8 bits ou microcontrolador do que um processador CISC de 32 bits com uma dúzia de modos de endereço de memória.

    
por 15.03.2012 / 21:58
2

Você não pode ver a codificação correta e desejada de um arquivo binário através do Bloco de Notas. Analise isso para referência futura. A maioria dos programas de edição de texto não analisa os formatos de codificação binária e espera-se que eles analisem a formatação do código de caracteres ASCII.

Portanto, abrir um arquivo binário em um editor de texto produzirá caracteres ASCII equivalentes que não fazem qualquer sentido do formato original dos dados binários, conforme analisados pelo editor de texto. Como mencionado, editores hexadecimais, e alguns possuem recursos binários, para visualizar o conteúdo em formato binário puro.

Você está incorreto que o conteúdo de um arquivo binário não pode ser entendido. Enquanto eles serão difíceis, e em arquiteturas de computador modernas extremamente difícil para desmontar manualmente de binário sozinho para instruções apropriadas reconhecidas pela CPU para execução (ou emulado / CPU virtual), etc., pode ser feito.

Como você acha que os emuladores estão programados? O desenvolvedor precisaria saber opcodes para poder programar o sistema fictício para reconhecer e se comportar como o hardware real faria de alguma maneira. As documentações explicam muitas arquiteturas de CPUs, e até as GPUs as possuem (embora mais secretas).

Outra coisa a notar é que no nível mais baixo, embora correlativo, os "dados binários" não são realmente um monte de zeros e uns, mas voltagens altas e baixas amplificadas / comutadas através de um circuito elétrico como corrente.

Binário geralmente é 1: 1 com isso, então faz muito sentido usar o sistema numérico para isso.

    
por 21.12.2013 / 22:05