65 votes

Comment écrire un désassembleur?

Je suis intéressé par l'écriture d'un x86 dissembler comme un projet éducatif.

La seule vraie ressource que j'ai trouvé est la Spirale de l'Espace, "Comment écrire un désassembleur". Tout cela donne un joli haut niveau de la description des différentes composantes d'un désassembleur, je suis intéressé par un peu plus détaillée des ressources. J'ai aussi pris un coup d'oeil rapide à MSNA du code source, mais c'est un peu un poids lourd à apprendre.

Je me rends compte de l'un des principaux défis de ce projet est plutôt grand jeu d'instructions x86, je vais avoir à gérer. Je suis également intéressé à la structure de base, de base désassembleur de liens, etc.

Quelqu'un peut-il m'indiquer détaillée des ressources sur l'écriture d'un x86 désassembleur?

63voto

Adam Rosenfield Points 176408

Jetez un oeil à l'article 17.2 de la 80386 Manuel de Référence du Programmeur. Un désassembleur est vraiment juste une glorifié finis de l'état de la machine. Les étapes de démontage sont:

  1. Vérifier si le courant de l'octet est une instruction préfixe octet (F3, F2ou F0); si oui, alors vous avez un REP/REPE/REPNE/LOCK préfixe. L'avance à l'octet suivant.
  2. Vérifiez pour voir si le courant de l'octet d'une adresse taille octets (67). Si oui, le décodage d'adresses dans le reste de l'instruction en mode 16 bits si actuellement en mode 32 bits, ou de décodage d'adresses en mode 32 bits si vous êtes actuellement en mode 16 bits
  3. Vérifiez pour voir si le courant octet est un opérande taille octets (66). Si oui, le décodage immédiat opérandes en mode 16 bits si actuellement en mode 32 bits, ou décoder immédiate des opérandes en mode 32 bits si vous êtes actuellement en mode 16 bits
  4. Vérifiez pour voir si le courant octet est un segment de remplacer octet (2E, 36, 3E, 26, 64ou 65). Si oui, utilisez le raccourci registre de segment pour le décodage des adresses au lieu du registre de segment par défaut.
  5. L'octet suivant est l'opcode. Si l'opcode est - 0F, puis c'est une longue opcode, et de lire l'octet suivant que l'étendue de l'opcode.
  6. Selon l'opcode, lire et décoder un Mod R/M octets, une Échelle de l'Indice de Base (SIB) octet, un déplacement (0, 1, 2 ou 4 octets), et/ou une valeur immédiate (0, 1, 2 ou 4 octets). Les tailles de ces champs dépendent de l'opcode , l'adresse, la taille et le correcteur de l'opérande taille remplace précédemment décodé.

L'opcode vous indique l'opération en cours. Les arguments de l'opcode peut être décodé forme les valeurs de la Mod R/M, SIB, des déplacements et de la valeur immédiate. Il y a beaucoup de possibilités et un grand nombre de cas, en raison de la nature complexe de x86. Voir les liens ci-dessus pour une explication plus approfondie.

22voto

Hannson Points 2165

Je voudrais vous recommandons de vérifier open source, désassembleurs, de préférence distorm et surtout "disOps (Jeux d'Instructions de Base de données)" (ctrl+la trouver sur la page).

La documentation elle-même est pleine de juicy informations sur les opérateurs et les instructions.

Citation de https://code.google.com/p/distorm/wiki/x86_x64_Machine_Code

80x86 Instruction:

Un 80x86 instruction est divisée en un nombre d'éléments:

  1. L'Instruction des préfixes, affecte le comportement de l'instruction du le fonctionnement.
  2. Obligatoire préfixe utilisé comme un opcode de l'octet pour les instructions SSE.
  3. Opcode octets, peut être un ou plusieurs octets (jusqu'à 3 octets).
  4. ModR/M octet est facultative et parfois peut contenir une partie de la opcode lui-même.
  5. SIB octet est facultatif et représente complexe de la mémoire d'indirection les formulaires.
  6. Le déplacement est facultatif et il est une valeur d'une variable de taille de octets(byte, word, long) et utilisé comme un décalage.
  7. Immédiate est facultatif et il est utilisé comme un nombre général de la valeur construite à partir d'une taille variable d'octets(byte, word, long).

Le format se présente comme suit:

/-------------------------------------------------------------------------------------------------------------------------------------------\
|*Prefixes | *Mandatory Prefix | *REX Prefix | Opcode Bytes | *ModR/M | *SIB | *Displacement (1,2 or 4 bytes) | *Immediate (1,2 or 4 bytes) |
\-------------------------------------------------------------------------------------------------------------------------------------------/
* means the element is optional.

Les structures de données et de décodage phases sont expliquées dans https://code.google.com/p/distorm/wiki/diStorm_Internals

Citation:

Le Décodage Des Phases

  1. [Préfixes]
  2. [Fetch Opcode]
  3. [Filtre Opcode]
  4. [Extrait de l'Opérande(s)]
  5. [Mise En Forme De Texte]
  6. [Hex Dump]
  7. [Décodé Instruction]

Chaque étape est expliquée aussi.


Les liens d'origine sont conservés pour des raisons historiques:

http://code.google.com/p/distorm/wiki/x86_x64_Machine_Code et http://code.google.com/p/distorm/wiki/diStorm_Internals

6voto

Charlie Martin Points 62306

Commencer avec quelques petit programme qui a été assemblés, et qui vous donne à la fois le code généré, et les instructions. Procurez-vous une référence à l' enseignement de l'architecture, et de travailler à travers certains de la génération de code avec la référence de l'architecture, à la main. Vous trouverez que les instructions ont une très stéréotypée de la structure de l' inst op op op avec le nombre de variables d'opérandes. Tout ce que vous devez faire est de traduire les hexadécimal ou octal représentation du code pour correspondre à ces instructions, un peu de jeu autour de vous le révéler.

Ce processus automatisé, est au cœur d'un désassembleur. Idéalement, vous allez probablement vouloir construire un n tableau de l'instruction des structures en interne (ou externe, si le programme est vraiment grand). Vous pouvez ensuite traduire de ce tableau dans les instructions en assembleur format.

4voto

Joshua Points 13231

Vous avez besoin d'un tableau d'opcodes à la charge de.

Les fondamentaux de recherche discbased est un trie, cependant un tableau fera bien assez si vous ne se soucient pas beaucoup sur la vitesse.

Pour obtenir la base de l'opcode type, beginswith match sur la table.

Il y a un peu de stock des moyens de décodage registre des arguments; cependant, il y a assez de cas particuliers d'exiger la mise en œuvre de la plupart d'entre eux individuellement.

Puisque c'est l'éducation, ont un oeil à ndisasm.

2voto

La caisse objdump sources - c'est un outil formidable, il contient de nombreux opcode tables et les sources peuvent fournir une belle base pour la fabrication de votre propre désassembleur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X