web-dev-qa-db-fra.com

Type de conversion de code utilisé dans les fichiers exécutables Linux

Je veux demander quel type d’encodage est utilisé pour créer des fichiers exécutables sous Linux, par exemple. hexadécemal, binaire ou autre chose. comment est-il converti? Est-il possible de récupérer le code d'origine à partir de ce fichier exécutable?

Voici un peu de code que j'ai:

ELF���������>�����%|�����@�������������������@�8��@���������������������@�������@�����7<�����7<������� ������������������f�����f���������������������� ������[�UPX!L
h�h�8����������?�E�h=��ڊ̓�N�    4���9ISloB�q�w�]ȉ.��,ς��Q䝦����#e��-�N����/�b,���d<��'��-E��6E�s�/�U���ly�V�Y2]"a��S�.�hU�|�S�J�I�2���X}
�G0�;���5d�$���.)

qu'est-ce que cela veut dire?

13
redchief

C'est binaire. Le code source a été compilé. Vous pouvez l'afficher dans un éditeur (un éditeur hexadécimal tel que bless pourrait permettre des modifications plus fines), mais vous devez vraiment savoir ce que vous faites. Ce n'est probablement bon que pour faire des changements de chaîne.

Pour tout ce qui est plus difficile, vous pouvez commencer à procéder au reverse engineering du binaire en Assembly . Ceci est souvent considéré comme le langage informatique analysable par l'homme le plus bas.

objdump -d helloworld | less

Mais cela inclura aussi beaucoup de bêtises du compilateur. Par exemple, si vous compilez le plus simple helloworld.cpp avec G ++ puis objdump, vous vous retrouvez avec 226 lignes (208 dépouillées) de beurk. Vous pourriez écrire un "bonjour le monde" en seulement 15 lignes de Assembly , le compiler et objdump il mais cela fleurit toujours en 166 lignes (dépouillé).

Si vous êtes assez bon avec Assembly, cela peut vous donner assez d'accès pour comprendre ce qui se passe, et même vous permettre de le changer ... Mais pour répondre à votre question initiale:

Vous ne pouvez pas reconvertir le code compilé en code source original .

Pardon. C'est une transformation à sens unique qui perd des informations (commentaires, formatage, concepts d'algorithmes lisibles, etc.), est liée statiquement à d'autres éléments et est généralement optimisée de manière à les rendre inintelligibles aux programmeurs les plus expérimentés et les meilleurs.

Pour vous donner une idée de l’ampleur du problème, l’idée même du logiciel de reverse engineering a son propre site Stack Exchange .

29
Oli

Je n'ai pas assez de points de réputation pour un commentaire, alors c'est une réponse:

Non, il n'est pas possible de le convertir "en arrière". Vous mentionnez le packer upx, avez-vous déjà lu le manuel de upx?

Si vous avez perdu la source ou si vous n'avez pas accès au code de quelqu'un d'autre, cela n'a pas d'importance, ce n'est tout simplement pas possible.

L'exécutable binaire a été produit avec un compilateur, ne croyez rien de ce qui est dit sur ce site, lisez simplement le manuel de ce compilateur. Ensuite, vous pouvez ajouter ici, dans quelle langue le code original a été écrit, quel compilateur a été utilisé, puis vous pouvez noter vous-même que ces étapes (prétraitement, compilation, liaison, peut-être compresser) ne sont pas inversées dans leur ensemble, mais ne peuvent que être analysé ce que l'auteur original aurait pu vouloir et écrit.

7
justabot

C'est probablement un fichier binaire (un fichier ELF) comme décrit ici:

https://en.wikipedia.org/wiki/Executable_and_Linkable_Format

Si vous l'avez modifié avec un éditeur de texte normal et enregistré vos modifications, ce n'était pas une bonne idée et vous l'avez peut-être détruit.

3
Bruni

Comme Oli l'a déjà souligné dans sa réponse, vous ne pouvez pas obtenir le code source très original d'un exécutable.

Lors de la compilation d'un code source (la compilation est conçue dans son acceptation plus large typique, d'où l'ensemble du processus qui "transforme" un code source en un exécutable), de nombreuses informations sont perdues.

Le préprocesseur C, par exemple, effectuera (entre autres) les tâches suivantes:

  • Interpréter, exécuter et supprimer les directives du préprocesseur (instructions #)
  • Supprimer les commentaires
  • Supprimer les espaces inutiles

D'autre part, ce qui n'est pas perdu lors de la compilation du code source est techniquement réversible en un code source fonctionnellement équivalent.

Ceci est dû au fait:

  • Les instructions binaires ont une correspondance 1: 1 avec les instructions de montage; L’assemblage d’un code source d’Assembly n’est qu’une simple conversion des instructions d’Assembly en instructions binaires reposant sur un tableau de correspondances; une seule instruction binaire est toujours identifiable et réversible en une seule instruction Assembly ;
  • Les instructions d'assemblage n'ont pas une correspondance de 1: 1 avec les instructions C; la compilation d'un code source C est généralement pas une simple conversion des instructions C en instructions d'assemblage basées sur un tableau des correspondances, en fait souvent le contraire généralement une instruction C est convertie en plusieurs instructions d'assemblage (souvent différentes en fonction du compilateur); cependant, les modèles de plusieurs instructions d'assemblage sont généralement identifiables et peuvent être convertis en une seule instruction C ;

Il existe des outils appelés décompilateurs dont le but est d'essayer de convertir un exécutable en un code source fonctionnellement équivalent. cependant, le résultat est généralement quelque chose très éloigné du code source très original (et généralement non compilable);

Considérez ce programme:

#include <stdio.h>

#define MESSAGE "Literal strings will be recovered" // This preprocessor directive won't be recovered

/*

This comment and the comment above won't be recovered

*/

int main(int argc, char* argv[]) {
    printf(MESSAGE);
    return 0;
}

En le compilant dans un exécutable et en le décompilant à nouveau dans un code source, c'est plus ou moins ce que vous récupérez habituellement (dans ce cas précis, j'ai utilisé gcc/ Boomerang ):

// address: 0x80483fb
int main(int argc, char **argv, char **envp) {
    printf("Literal strings will be recovered");
    return 0;
}

Comme prédit:

  • Les directives du préprocesseur sont manquantes
  • Il manque des commentaires (à part // address: 0x80483fb qui a été ajouté par le décompilateur)
  • Il manque des espaces inutiles (mis à part les nouvelles lignes et les totalisations ajoutées par le décompilateur)

C'est aussi un très bon résultat. il n'est pas rare que des instructions d'assemblage en ligne soient intégrées au code:

asm("Assembly_instruction");
__asm__("Assembly_instruction");

La ligne de fond est (comme indiqué déjà dans les autres réponses): vous ne pouvez pas obtenir la source très originale d'un exécutable *.

* Cependant, en fonction de l'exécutable et de votre chance, vous pourriez pouvoir obtenir quelque chose à l'aide d'un décompilateur.

3
kos

Les exécutables sont généralement binaires si vous parlez de programmes compilés. Vous pouvez trouver plus d'informations en utilisant file path/to/executable. Vous pouvez afficher les exécutables binaires au format hexadécimal en utilisant par exemple hexdump -C path/to/executable | less (quel que soit le bien que cela vous ferait). Si vous voulez "reconvertir sa forme originale", vous devez utiliser un décompilateur approprié voir cet article, par exemple , bien que cela vous donne un code assez illisible, pas l'original avec lequel il a été compilé . S'il ne s'agit pas d'un fichier binaire compilé, il s'agirait d'une sorte de script exécutable, qui devrait être facilement lisible dans n'importe quel éditeur de texte. Ce que vous nous avez montré ici est probablement un exécutable compilé. ELF signifie "format exécutable et lien", qui est un format binaire commun sur les systèmes Linux/Unix. Il est possible d'extraire les parties de chaîne lisibles des fichiers binaires en utilisant strings path/to/executable, si c'est ce dont vous avez besoin.

2
Hinz