Comment jeter un œil aux binaires à partir de la ligne de commande Linux

Contenu

Un terminal Linux stylisé avec des lignes de texte vert sur un ordinateur portable.

Avez-vous un fichier mystérieux? Sous Linux file La commande vous dira rapidement de quel type de fichier il s'agit. Malgré cela, si c'est un fichier binaire, vous pouvez obtenir plus d'informations à ce sujet. file a toute une série de compagnons d'écurie qui vous aideront à l'analyser. Nous allons vous montrer comment utiliser certains de ces outils.

Identification des types de fichiers

Les fichiers ont souvent des caractéristiques qui permettent aux progiciels d'identifier de quel type de fichier il s'agit., ainsi que ce que les données qu'il contient représentent. Il ne servirait à rien d'essayer d'ouvrir un fichier PNG dans un lecteur de musique MP3., il est donc utile et pragmatique pour un fichier de porter une sorte d'identification.

Il peut s'agir de quelques octets de signature au début du fichier. Cela permet à un fichier d'être explicite sur son format et son contenu. Parfois, le type de fichier est déduit d'un aspect distinctif de l'organisation interne des données elles-mêmes, connue sous le nom d'architecture de fichiers.

Certains systèmes d'exploitation, comme Windows, sont absolument guidés par l'extension d'un fichier. Vous pouvez l'appeler crédule ou confiant, mais Windows suppose que tout fichier avec l'extension DOCX est vraiment un fichier de traitement de texte DOCX. Linux n'est pas comme ça, dès que tu verras. Vous voulez une preuve et regardez dans l'archive pour la trouver.

Les outils décrits ici étaient déjà installés dans les distributions Manjaro 20, Feutre 21 et Ubuntu 20.04 Qu'utilisons-nous pour rechercher ce poste?. Commençons notre enquête en utilisant Les file commander.

Utilisation de la commande de fichier

Nous avons une collection de différents types de fichiers dans notre répertoire actuel. Ils sont un mélange de documents, code source, exécutables et fichiers texte.

Les ls la commande nous montrera ce qu'il y a dans le répertoire, et le -hl L'option (tailles lisibles par l'homme, longue liste) il nous montrera la taille de chaque fichier:

ls -hl

Essayons file sur certains d'entre eux et voyons ce que nous obtenons:

fichier build_instructions.odt
fichier build_instructions.pdf
fichier COBOL_Report_Apr60.djvu

Les trois formats de fichiers sont correctement identifiés. Dans la mesure du possible, file nous donne un peu plus d'informations. Le fichier PDF est signalé comme étant dans le format de version 1.5.

Même si on change le nom du fichier ODT pour qu'il ait une extension avec la valeur arbitraire de XYZ, le fichier est toujours correctement identifié, à la fois au sein de la Files explorateur de fichiers et sur la ligne de commande en utilisant file.

Fichier OpenDocument correctement identifié dans l'explorateur de fichiers d'archive, bien que son extension soit XYZ.

Dans Files Navigateur de fichiers, se voit attribuer la bonne icône. Sur la ligne de commande, file ignorez l'extension et regardez à l'intérieur du fichier pour définir son type:

fichier build_instructions.xyz

À l'aide de file dans les médias, tels que des fichiers d'image et de musique, fournit généralement des informations sur son format, codage, résolution, etc.

fichier screenshot.png
fichier screenshot.jpg
fichier Pachelbel_Canon_In_D.mp3

avec curiosité, même avec des fichiers texte, file ne juge pas le fichier par son extension. Par exemple, si vous avez un fichier avec l’extension “.c”, contenant du texte brut standard mais pas de code source, file ne le confondez pas avec un véritable C fichier de code source:

fichier fonction+en-têtes.h
fichier makefile
fichier bonjour.c

file identifie correctement le fichier d'en-tête (“.h”) dans le cadre d'une collection de fichiers de code source C, et vous savez que le makefile est un script.

Utilisation de l'archive avec des fichiers binaires

Les fichiers binaires sont plus d’un “boîte noire” que d’autres. Les fichiers images peuvent être visualisés, les fichiers audio peuvent être lus et les fichiers de documents peuvent être ouverts avec le progiciel approprié. Malgré cela, les binaires sont un plus grand défi.

Par exemple, les archives “Bonjour” et “Naine blanche” sont des exécutables binaires. ce sont des programmes. Le fichier appelé “wd.o” est un fichier objet. Quand un compilateur compile le code source, un ou plusieurs fichiers objets sont créés. Ceux-ci contiennent le code machine que l’ordinateur finira par exécuter lorsque le programme terminé est exécuté., ainsi que des informations pour l’éditeur de liens. l’éditeur de liens vérifie chaque fichier objet pour les appels de fonction aux bibliothèques. Les relie aux bibliothèques utilisées par le programme. la sortie de cette procédure est un fichier exécutable.

L'archive “regarder.exe” est un exécutable binaire qui a été compilé pour s’exécuter sous Windows:

fichier wd
fichier wd.o
fichier hello
surveillance des fichiers.exe

Prendre le dernier premier file nous indique que le fichier “regarder.exe” est un programme de console exécutable pe32 + pour la famille de processeurs x86 dans Microsoft Windows. PE signifie format exécutable portable, qui a des versions de 32 et 64 morceaux. Le PE32 est la version de 32 bits et le PE32 + est la version de 64 morceaux.

Les trois autres fichiers sont tous identifiés comme Format exécutable et liable (ELFE) enregistrements. il s’agit d’une norme pour les fichiers exécutables et les fichiers d’objets partagés, en tant que bibliothèques. Nous verrons le format d'en-tête ELF sous peu.

Ce qui pourrait attirer votre attention, c'est que les deux exécutables (“Naine blanche” et “Bonjour”) sont identifiés comme Base de normes Linux (LSB) objets partagés, et le fichier objet “wd.o” est identifié comme un LSB déplaçable. Le mot exécutable est évident en son absence.

Les fichiers objets sont déplaçables, ce qui signifie que le code qu'ils contiennent peut être chargé en mémoire à n'importe quel endroit. Les exécutables sont répertoriés comme objets partagés car ils ont été créés par l'éditeur de liens à partir des fichiers objets de manière à hériter de cette capacité.

Cela permet Randomisation de la disposition de l'espace d'adressage (ASMR) pour charger des exécutables en mémoire aux adresses de votre choix. Les exécutables standard ont une adresse de charge utile codée en dur dans leurs en-têtes, qui dicte où ils sont chargés en mémoire.

L'ASMR est une technique de sécurité. Le chargement d'exécutables en mémoire à des adresses prévisibles les rend vulnérables aux attaques. En effet, les attaquants connaîtront toujours leurs points d'entrée et l'emplacement de leurs fonctions.. Exécutables indépendants de la position (TARTE) placé dans une direction aléatoire surmonte cette susceptibilité.

Si nous compiler notre programme avec lui gcc compilateur et fournir le -no-pie option, nous allons générer un exécutable conventionnel.

Les -o L'option (fichier de sortie) nous permet de donner un nom à notre exécutable:

gcc -o bonjour -no-pie bonjour.c

nous utiliserons file dans le nouvel exécutable et voir ce qui a changé:

fichier hello

La taille de l'exécutable est la même qu'avant (17 Ko):

ls -hl bonjour

Le binaire est maintenant identifié comme un exécutable standard. Nous le faisons à des fins de démonstration uniquement. Si vous compilez des applications de cette façon, vous perdrez tous les avantages de l'ASMR.

Pourquoi un exécutable est-il si gros?

Notre exemple hello Le programme a 17 Ko, donc ça pourrait difficilement être appelé grand, mais tout est relatif. Le code source est de 120 octets:

chat bonjour.c

Ce qui augmente le volume du binaire si tout ce qu'il fait est d'imprimer une chaîne dans la fenêtre du terminal? Nous savons qu'il existe un en-tête ELF, mais il n'a que 64 octets de long pour un binaire de 64 morceaux. Clairement, ça doit être autre chose:

ls -hl bonjour

Allons-y scanner le binaire avec le strings commande comme première étape simple pour découvrir ce qu'elle contient. Nous allons le canaliser dans less:

bonjour les cordes | moins

Il y a beaucoup de chaînes dans le binaire, en même temps que le “Bonjour, monde geek!” de notre code source. La plupart d'entre eux sont des étiquettes pour les régions dans le binaire et les noms et les informations de lien des objets partagés. Ceux-ci incluent les bibliothèques et les fonctions au sein de ces bibliothèques, dont dépend le binaire.

Les ldd commander nous montre les dépendances d'objets partagés d'un binaire:

bonjour

Il y a trois entrées dans la sortie et deux d'entre elles incluent un chemin de répertoire (le premier non):

  • linux-vdso.so: Objet partagé dynamique virtuel (VDSO) est un mécanisme du noyau qui permet à un binaire de l'espace utilisateur d'accéder à un ensemble de routines de l'espace du noyau. Cette éviter de surcharger un commutateur de contexte depuis le mode noyau utilisateur. Les objets partagés VDSO adhèrent au format de format pouvant être lié et exécutable (ELFE), ce qui leur permet de se lier dynamiquement au binaire au moment de l'exécution. VDSO est attribué dynamiquement et exploite ASMR. La capacité VDSO est fournie par la norme Bibliothèque GNU C si le noyau supporte le schéma ASMR.
  • libc.so.6: Les Bibliothèque GNU C objet partagé.
  • /lib64/ld-linux-x86-64.so.2: C'est l'éditeur de liens dynamique que le binaire veut utiliser. L'éditeur de liens dynamique interroger le binaire pour savoir quelles dépendances il a. Jetez ces objets partagés en mémoire. Préparer le binaire à exécuter et pouvoir trouver et saisir les dépendances en mémoire. Après, lancer le programme.

L'en-tête ELF

Pouvons examiner et décoder l'en-tête ELF en utilisant le readelf utilitaire et -h (en-tête de fichier) option:

readelf -h bonjour

L'en-tête est interprété pour nous.

Le premier octet de tous les binaires ELF est défini sur la valeur hexadécimale 0x7F. Les trois octets suivants sont définis sur 0x45, 0x4C et 0x46. Le premier octet est un indicateur qui identifie le fichier en tant que binaire ELF. Pour que ce soit très clair, l’orthographe des trois octets suivants “ELFE” au ASCII:

  • Classe: Indique si le binaire est un exécutable de 32 O 64 morceaux (1 = 32, 2 = 64).
  • Données: Indique le endianité en service. L'encodage endian définit la façon dont les nombres multi-octets sont stockés. En codage big-endian, un nombre est stocké avec ses bits les plus significatifs en premier. En codage little-endian, le nombre est stocké avec les bits les moins significatifs en premier.
  • Version: La version ELF (en ce moment, il est 1).
  • TU / AIDER: Représente le type de interface binaire d'application en service. Ceci établit l'interface entre deux modules binaires, en tant que programme et bibliothèque partagés.
  • Version ABI: La version ABI.
  • Écrit: Le type binaire ELF. Les valeurs communes sont ET_REL pour une ressource délocalisable (en tant que fichier objet), ET_EXEC pour un exécutable compilé avec le -no-pie drapeau, et ET_DYN pour un exécutable conforme à l'ASMR.
  • Machine: Les jeu d'instructions d'architecture. Ceci indique la plate-forme cible pour laquelle le binaire a été créé.
  • Version: Toujours réglé sur 1, pour cette version d'ELF.
  • Adresse du point d'entrée: L'adresse mémoire dans le binaire à laquelle l'exécution commence.

Les autres messages sont des tailles et des nombres de régions et de sections dans le binaire afin que leurs emplacements puissent être calculés.

Un rapide coup d'œil aux huit premiers octets du binaire avec hexdump afficher l’octet et la chaîne de signature “ELFE” dans les quatre premiers octets du fichier. Les -C (canonique) nous donne la représentation ASCII des octets avec leurs valeurs hexadécimales, et la -n L'option (le numéro) nous permet de spécifier combien d'octets nous voulons voir:

hexdump -C -n 8 Bonjour

objdump et la vue granulaire

Si vous voulez voir les détails, vous pouvez utiliser le objdumpcommande avec le -d (démonter) option:

objdump -d bonjour | moins

Cela désassemble le code machine exécutable et l'affiche en octets hexadécimaux avec le langage d'assemblage comme. L'emplacement de l'adresse du premier bye dans chaque ligne est indiqué à l'extrême gauche.

Ceci n'est utile que si vous savez lire le langage assembleur ou si vous êtes curieux de savoir ce qui se passe derrière le rideau. Il y a beaucoup de résultats, donc nous le canalisons vers less.

Compiler et lier

Il existe de nombreuses alternatives à la compilation d'un binaire. Par exemple, le développeur choisit d'inclure ou non les informations de débogage. La façon dont le binaire est lié influence également son contenu et sa taille. Si les références binaires partagent des objets en tant que dépendances externes, sera plus petit que celui auquel les dépendances sont statiquement liées.

La plupart des développeurs connaissent déjà les commandes que nous avons décrites ici. Pour les autres, malgré cela, offrent des moyens faciles de fouiller et de voir ce qu'il y a à l'intérieur de la boîte noire binaire.

Abonnez-vous à notre newsletter

Nous ne vous enverrons pas de courrier SPAM. Nous le détestons autant que vous.