OD ?? Mais à qui doit-on cette merveille ?
Le programme OD à été écrit par Jim Meyering.
Je le salue bien bas, et de la part de tous les fouineurs, fureteurs, insatiables curieux, merci ! :-)
Od fait partie du paquet coreutils et l'on peut obtenir plus d'informations sur ce paquet avec la commande :
info coreutils
Sur od :
man od
À quoi sert-il ?
À l'origine, à afficher le contenu d'un fichier en octal, d'où son nom, mais en fait od peut faire bien plus. J'ai fait la connaissance d'od grâce à mon ami cep :-) :-) :-) :-), et je l'utilise majoritairement pour afficher le contenu de fichiers en hexadécimal, fichiers au sens large, car tout est fichier.
On peut en réalité s'en servir pour afficher tout contenu, qu'il ne modifiera ou n'altèrera en rien, aucun risque de fausses manoeuvres n'étant à déplorer. Il est particulièrement et principalement utile lorsqu'il s'agit d'un contenu binaire. N'avez vous jamais été effrayé par ce type de message ? :
:~$ less /bin/echo
"/bin/echo" may be a binary file. See it anyway?
Mais que puis-je faire ? :-( Dois-je accepter ? Ce message ressemble à s'y méprendre à l'annonce du jugement dernier ! :-( J'ai si peur ! :-(
C'est ici qu'od montre tout son potentiel. Il peut afficher en toute quiètude le contenu d'un binaire, que ce soit celui d'un fichier régulier, d'un exécutable ex : /bin/echo, du disque dur ex : /dev/hda, d'une partition ex : /dev/hda1, de la mémoire physique ex : /dev/mem, de la mémoire virtuelle ex : /dev/kmem. L'affichage est disponible pour différentes bases : hexadécimale, décimale, octale et sous de nombreux formats.
Od est compatible avec l'utilisation de tubes, en couple avec grep il est très sympathique. ;-)
Fureter, observer, étudier les binaires sous toutes leurs coutures, voilà à mes yeux l'attrait incontestable de cet outil nommé od. Od je t'ai apporté des fleurs, des roses, oui rouges ! Je..., je..., je t'aime ! :-)
Un bref descriptif :
:~$ man /usr/share/man/man1/od.1.gz | grep -A1 ^"NAME"
NAME
od - dump files in octal and other formats
Bah, od = Octal Dump !? ;-)
Maintenant l'on peut lire un court extrait de la page française du manuel :
:~$ man od | grep -A1 ^"NOM"
NOM
od - Afficher le contenu d’un fichier en octal
À qui doit-on cette traduction ? :
:~$ man od | grep -A6 ^"TRADUCTION"
TRADUCTION
Cette page de manuel a été traduite par Michel Robitaille <robitail AT
iro DOT umontreal DOT ca> et mise à jour pour Debian par Jean-Luc
Coulon (f5ibh) <jean-luc DOT coulon AT wanadoo DOT fr> et les membres
de la liste <debian-l10n-french AT lists DOT debian DOT org>. Veuillez
signaler toute erreur de traduction par un rapport de bogue sur le
paquet manpages-fr-extra.
Tout est dit non ?? On installe le paquet manpages-fr-extra si ce n'est déjà fait ! Bah oui, puisqu'on vous le dit ! :-)
On ne sait pas comment faire ? À quoi ça sert que cep se décarcasse ?
Les pages du manuel d'od sont très explicites, pour cette raison, cet article privilégiera les exemples pour illustrer des utilisations potentielles.
Une précision : les options -j pour le saut, le déplacement, et -N pour la taille de la partie du fichier que l'on veut afficher, peuvent être exprimées en décimal ou en hexadécimal. Que l'on choisisse de donner cette information en hexadécimal ou en décimal n'a aucun impact sur l'affichage. Il s'agit simplement de faciliter la tâche de l'utilisateur. Par défaut, si l'on n'utilise ni -j ni -N, le fichier sera affiché dans sa totalité en commençant à l'offset 0x0.
Lorsque l'on observe la sortie d'od, l'on notera dans le cadre d'une utilisation générale, trois parties :
:~$ sudo od -Ax -tx1z -N 0x10 /dev/hda
eb 48 90 00 00 00 00 00 00 00 00 00 00 00 00 00 >.H..............<
De gauche à droite :
Les pages de manuels vous semblent-elles obscures ? Ou encore, pensiez-vous, tels que moi, connaître l'indispensable quand à leur utilisation ? Faites un simple test, parcourez le lien suivant, et lisez-le de A jusqu'à Z :
RTFM : lisez le manuel ! par M@teo21
Poursuivons, le synopsis du manuel od contient trois lignes :
L'adresse, dont on peut spécifier la Base via l'option -A, correspond à la position de chaque début de ligne dans le fichier. Elle peut être exprimée dans de multiples bases : d pour une représentation décimale, o pour octale (pour celle-ci, inutile d'utiliser l'option -A, par défaut, l'adresse est indiquée en octal), x pour hexadécimale, n pour aucune (none). (Voir la partie concernant les bases dans le manuel).
L'option -j spécifie le déplacement, soit en décimal, soit en hexadécimal, l'adresse désigne alors la position atteinte. Comme l'affichage se fait par ligne de x octets, l'adresse sera incrémentée pour chaque nouvelle ligne. Il est à noter que nous pouvons utiliser des multiples pour ce déplacement, allant, en théorie de l'octet au yotta. Dans la pratique, on préférera d'autres solutions à partir d'une certaine taille. À propos des unités :
:~$ man units
Enchaînons par quelques exemples :
:~$ man od | grep -A1 -e "BASE"$
-A, --address-radix=BASE définir la BASE dans laquelle les déplacements dans les fichiers
sont affichés
Adresse exprimée en hexadécimal :
:~$ sudo od -Ax -tx1z -j 0x1fe -N 2 /dev/hda
55 aa >U.<
Adresse exprimée en octal :
L'on remarquera que la base utilisée pour l'adresse est indépendante de la base servant à afficher le contenu, ici octale pour l'adresse et hexadécimale pour le contenu. Il en est également ainsi pour le saut, (le déplacement) indiqué par l'option -j, la base utilisée pour celui-ci n'a pas d'impact sur celle affichée pour l'adresse.
:~$ sudo od -Ao -tx1z -j 0x1fe -N 2 /dev/hda
55 aa >U.<
Adresse exprimée en décimal :
:~$ sudo od -Ad -tx1z -j 510 -N 2 /dev/hda
55 aa >U.<
Bien sûr, par défaut, dès lors que l'on ne sélectionne pas l'option -j pour se positionner dans le fichier, la première adresse sera égale à zéro, puis les lignes suivantes seront incrémentées en fonction du déplacement. Un dernier exemple avec le déplacement en décimal :
:~$ sudo od -Ad -tx1 -N 0x20 /dev/hda
eb 48 90 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Ici chaque ligne fait 0x10 soit 16 octets, la seconde ligne commence à 16 et la troisième à 32
Enfin, si l'on préfère masquer l'adresse, l'argument n pour none remplira parfaitement cette mission.
:~$ sudo od -An -tx1z -j 0x1fe -N 2 /dev/hda
55 aa >U.<
Si l'on a bien lu l'article de M@teo21, nous devrions comprendre cette ligne.
Les seules options dont nous disposons sont celles entre crochets, et l'on n'y voit pas de A. Nous ne pourrons en conséquence qu'utiliser la base par défaut dans le champ Adresse. Eh, oui, octal dump : octal. :-( Pour le contenu nous avons encore un peu de choix.
Nous pouvons demander un déplacement en faisant précéder sa valeur du signe + et en utilisant divers multiples. J'ai créé un fichier d'une taille suffisante pour l'exemple suivant afin d'illustrer l'utilisation d'un multiple. Lorsque vous utilisez la commande dd assurez-vous d'être bien réveillé, une erreur dans la destination ou la taille de la copie pourrait induire de tristes déconvenues. ;-)
:~$ dd if=/dev/random of=./cccc.bin bs=1 count=528
Déplacement avec un multiple :
:~$ od -x ./cccc.bin +1b 1ae2 6f6c 46bc 6bd6 aa65 d855 0a09 e791
En octal 1000 équivaut à 512 en décimal, soit ici le multiplicateur b, comme mon fichier faisait 528 octets, nous apercevons la dernière ligne.
Ici, on voit apparaître une nouvelle possibilité l'étiquette.
L'étiquette est une pseudo adresse, dont on peut indiquer la valeur de départ. Celle-ci sera incrémentée à chaque ligne, tout comme le champ adresse, elle se situera juste à côté d'elle, démarquée par des parenthèses.
:~$ od --traditional -Ax -tx1z -N 0x20 ./cccc.bin +0 +0x10 000000 (000010) 4c 6f 7c 41 15 6c 15 b1 e8 b5 80 8b 46 4c 58 22 >Lo|A.l......FLX"< 000010 (000020) 7e c7 d5 25 fe 80 b9 93 ab 0e d7 44 dd 13 78 7e >~..%.......D..x~< 000020 (000030)
On peut afficher le contenu d'un fichier sous diverses bases (décimales, octales, hexadécimales) et avec divers formats.
On dispose de formats traditionnels a, b, c, d, f, i, l, o, s, x, prédéfinis, que l'on peut cumuler, pour le détail de ces formats on consulte le manuel. Allez, je vous aide un peu, la commande suivante devrait vous faciliter la tâche :
:~$ man od | grep -A27 "Les sp"
Pour celui-ci :
:~$ man od | grep -A1 -e " -a"
-a identique à -t a, afficher les caractères par leur nom, en igno‐
rant le bit de poid fort
Une explication :
Pourquoi ignorer le bit de poids fort ? Parce qu'il s'agit de caractères, plus précisémment de caractères ASCII, (voir man ascii), et que ceux-ci s'étendent de 0 à 0x7f.
Un caractère est codé sur 8 bits, valeur maximum 0xff, si l'on retire le bit de poids
fort à 0xff ceci nous donne 0x7f, soit la valeur maximum d'un caractère ASCII. :-)
Un autre cas mérite peut-être un éclaircissement, l'option -S :
:~$ man od | grep -A1 -e "-S"
-S, --strings[=N]
afficher les chaînes d’au moins N caractères graphiques
Voici pour l'exemple le contenu d'un binaire, en fait une partie de la pile d'un programme que j'ai sauvegardé avec les arguments append memory /chemin_vers_le_fichier début fin sous GDB.
:~$ od -Ax -tx1z ./a_bin.bin 000000 70 6f 6d 6d 65 00 70 6f 69 72 65 00 61 6e 61 6e >pomme.poire.anan< 000010 61 73 00 6d 61 6e 64 61 72 69 6e 65 00 1a 8d bf >as.mandarine....< 000020 ff ff ff 7f ff ff ff ff >........< 000028
Ce que l'on cherche se sont des chaînes de caractères, composées de caractères graphiques, délimitées par 0.
L'option -S n'utilisera que les chaînes composées de N caractères et enverra le résultat sur l'écran :
:~$ od -S9 ./a_bin.bin
0000023 mandarine
Il serait vain d'essayer l'option -S sur un fichier texte, car les chaînes de caractères n'y sont pas séparées par le caractère NUL '\0', mais par des espaces, tabulations, mise-à-la-ligne, etc... C'est pour cela que j'ai utilisé un binaire, dans mon exemple c'était une partie de structure.
Poursuivons par quelques exemples d'utilisation des formats, voici les dix premiers octets de mon fichier ./tryod.bin, que l'on ne cherche aucune signification particulière à ce fichier, il n'y en pas et il ne sert à rien. :-)
Commençons par le format par défaut sans aucune option, donc en octal :
:~$ od ./tryod.bin 0000000 037432 036102 166000 037441 151661 053516 021450 060230 0000020
Voyons, maintenant les formats traditionnels, qui peuvent être cumulés, démonstration :
:~$ od -Ax -abcdfilosx -N 0x10 ./tryod.bin
000000 sub ? B < nul l ! ? 1 S N W ( # can `
032 077 102 074 000 354 041 077 261 323 116 127 050 043 230 140
032 ? B < \0 354 ! ? 261 323 N W ( # 230 `
16154 15426 60416 16161 54193 22350 9000 24728
1,185586e-02 6,325073e-01 2,274086e+14 8,770120e+19
1010974490 1059187712 1464783793 1620583208
1010974490 1059187712 1464783793 1620583208
037432 036102 166000 037441 151661 053516 021450 060230
16154 15426 -5120 16161 -11343 22350 9000 24728
3f1a 3c42 ec00 3f21 d3b1 574e 2328 6098
000010
L'inconvénient des formats traditionnels c'est qu'il sont prédéfinis, et ne peuvent être modifiés, le chapitre suivant nous offre d'autres possibilités.
L'argument -t permet d'affiner le type, le préciser, le modeler à ses besoins pour ce qui concerne d, o, u, x, soit en ajoutant la précision sous forme de chiffres(1-2-4-8) juste derrière, soit en utilisant des précisions disponibles telles que C, S, I, L, pour les précédants, ou encore F, D, L pour les float (type f).:
Bien sûr, le détail de tout ceci est accessible avec man od.
Peut-on cumuler lorsqu'il s'agit de types particuliers ? Allez, soyons fous, afficher pour la première lignes des 16 bits en hexadécimal et des 64 bits en octal pour la seconde? Pour la troisième en hexadécimal sur 8 bits, la quatrième en octal sur 4 bits, la cinquième en décimal non signé sur 4 bits et la sixième en octal sur 4 bits ! Hein ! Non mais dites-donc, faut pas pousser !... :-)
Afficher une même ligne sous différents formats en une seule commande, allons vous n'êtes pas de ce monde, vous rêvez ! Enfant ! Ça ne marchera jamais, jamais vous dis-je ! :-( Soyez raisonnable, je vous en conjure ! :-(
:~$ od -Ax -tx1x2o1o4o8u1 -N 16 ./tryod.bin
000000 1a 3f 42 3c 00 ec 21 3f b1 d3 4e 57 28 23 98 60
3f1a 3c42 ec00 3f21 d3b1 574e 2328 6098
032 077 102 074 000 354 041 077 261 323 116 127 050 043 230 140
07420437432 07710366000 12723551661 14046021450
0374417300007420437432 0602301062412723551661
26 63 66 60 0 236 33 63 177 211 78 87 40 35 152 96
000010
Mais cela marche ! :-) :-)
Voici un autre exemple :
Comme on le voit ici, il s'agit d'adresses en LE :
:~$ od -Ax -tx1 ./unbin.bin
000000 34 80 04 80 14 81 04 08 00 80 04 08 28 81 04 08
000010
Il suffit de modifier la précision du type et voici, oh, c'est en BE :
:~$ od -Ax -tx4 ./unbin.bin
000000 80048034 08048114 08048000 08048128
000010
Alors, qu'attendez-vous ! Créez votre propre recette ! ;-)
Et si vous vous demandiez ce qu'étaient ces abréviations bizarres LE et BE, alors je ne dirais qu'un seul mot : Endianness.
Ah !..., je vous vois venir, est-il possible de modifier également la taille de l'affichage ! Et pourquoi pas repasser vos chemises ! C'est un monde tout de même !... Ben si, c'est possible ! L'argument -w est là à cette fin. :-) Un exemple :
:~$ od -Ax -tx2 -N 16 -w2 ./tryod.bin
000000 3f1a
000002 3c42
000004 ec00
000006 3f21
000008 d3b1
00000a 574e
00000c 2328
00000e 6098
000010
:~$ od -Ax -tx2 -N 16 -w4 ./tryod.bin
000000 3f1a 3c42
000004 ec00 3f21
000008 d3b1 574e
00000c 2328 6098
000010
Une dernière chose avant de passer au chapitre suivant, lorsque l'on utilise des fichiers de taille très importante od ralentit très sensiblement. Od a été conçu à l'origine pour afficher le contenu de fichiers, et lui demander de se déplacer dans une partition de plusieurs gigas n'est pas ce qu'il affectionne. L'association dd | od est parfaite pour cette situation, en envoyant la sortie de dd via un tube à l'entrée d'od nous ne sommes plus pénalisés par des délais conséquents.
:~$ sudo dd if=/dev/hda6 bs=4096 skip=2173078 count=1 2>/dev/null | od -Ax -tx1z -N 0x10
000000 1a 3f 42 3c 00 ec 21 3f b1 d3 4e 57 28 23 98 60 >.?B<..!?..NW(#.`<
000010
ASCII ?
man ascii
Un bref descriptif des différentes classes de caractères est disponible avec la commande suivante :
man isascii
L'option -z d'od affichera, en complément de -t, tous les caractères imprimables (compris entre 0x20 et 0x7e inclus) sur la partie de droite, entre les chevrons > et <. Tout autre caractère, en fait les caractères de contrôle, sera représenté par un .
Le fichier suivant, (créé uniquement pour l'exemple), comprend tous les caractères ASCII, ainsi nous verrons ce qui est affiché sur la partie de droite.
:~$ od -Ax -tx1z ./ascii_char.bin
000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f >................< 000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f >................< 000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f > !"#$%&'()*+,-./< 000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f >0123456789:;<=>?< 000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f >@ABCDEFGHIJKLMNO< 000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f >PQRSTUVWXYZ[\]^_< 000060 60 61 62 63 64 65 66 66 68 69 6a 6b 6c 6d 6e 6f >`abcdeffhijklmno< 000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f >pqrstuvwxyz{|}~.< 000080
Bien sûr, on peut ne pas vouloir afficher cette partie, dans ce cas, on oublie l'option -z.
:~$ od -Ax -tx1 ./ascii_char.bin
000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
000060 60 61 62 63 64 65 66 66 68 69 6a 6b 6c 6d 6e 6f
000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
000080
Pour une utilisation basique, on peut facilement concaténer plusieurs fichiers. Dans l'exemple suivant les fichiers sont excessivement courts, mais il n'y a pas de limitations, ils pourraient être bien plus long et il pourrait y en avoir plus.
Pour cet exemple, et par fainéantise, j'ai confié à /dev/urandom la difficile tâche de créer des nombres aléatoires, et à dd celui de les copier dans un fichier.
:~$ dd if=/dev/urandom of=./aaaa.bin count=32 bs=1 :~$ dd if=/dev/urandom of=./bbbb.bin count=32 bs=1
:~$ od -Ax -tx1z ./aaaa.bin 000000 3a b0 c1 0f d6 e2 3e 49 fd 5d d3 0d d6 91 96 2d >:.....>I.].....-< 000010 8f df 9d e2 f7 92 a4 0f 53 ad 75 3c 81 28 37 5b >........S.u<.(7[< 000020 :~$ od -Ax -tx1z ./bbbb.bin 000000 1f 89 2e 5a 35 31 d7 61 9b ef 74 b7 e8 b3 73 be >...Z51.a..t...s.< 000010 10 c3 44 11 85 c6 ff 10 78 60 54 3b 4e 68 1f cf >..D.....x`T;Nh..< 000020
Voici la concaténation :
:~$ od -Ax -tx1z ./aaaa.bin ./bbbb.bin 000000 3a b0 c1 0f d6 e2 3e 49 fd 5d d3 0d d6 91 96 2d >:.....>I.].....-< 000010 8f df 9d e2 f7 92 a4 0f 53 ad 75 3c 81 28 37 5b >........S.u<.(7[< 000020 1f 89 2e 5a 35 31 d7 61 9b ef 74 b7 e8 b3 73 be >...Z51.a..t...s.< 000030 10 c3 44 11 85 c6 ff 10 78 60 54 3b 4e 68 1f cf >..D.....x`T;Nh..< 000040
Si vous devez utiliser les options -j pour le saut et -N pour le nombre d'octets à afficher, notez bien ceci. Cela s'appliquera au résultat de la concaténation, autrement dit, si dans l'exemple précédent j'applique un décalage de 0x20, je ne verrais que le deuxième fichier. Si je n'applique pas de décalage mais que je demande un affichage de 0x20 octets, c'est le deuxième fichier que je ne verrais pas.
Une clarification suite à une observation de mon ami cep, ;-), afin de lever toute ambiguïté : la concaténation est binaire. Les deux fichiers sont mis bout à bout, le premier octet du second fichier commençant juste après le dernier du précédent. La signification ASCII ne sera pas interprétée, exit donc une éventuelle mise à la ligne.
Pour concaténer des fichiers texte l'on se tournera vers cat.
:~$ man cat
Pour l'experience suivante j'ai créé un fichier contenant un certain nombre de zéros, ceci pour montrer à quoi sert l'option -v.
:~$ od -Ax -tx1z -w4 ./un.bin
000000 00 00 00 00 >....<
*
000008 3b 2d 29 0a >;-).<
00000c
:~$ od -Ax -tx1z -w4 -v ./un.bin 000000 00 00 00 00 >....< 000004 00 00 00 00 >....< 000008 3b 2d 29 0a >;-).< 00000c
En temps normal, dès lors qu'il y a plus d'une ligne composée exclusivement d'un même caractère, peu importe lequel, celles situées après la première sont symbolisées par *, ce qui évite un affichage inutile. L'option -v, le mode verbeux, vous montrera l'intégralité du fichier.
Si vous avez omis d'entrer le nom du fichier, entrez la combinaison suivante : CTRL + c afin de fermer le programme, car par défaut c'est /dev/stdin (alias stdin, alias le descripteur 0, alias /proc/self/fd/0) qui servira d'entrée, soit, par convention, le clavier. ;-) Et si, comble de malchance, vous avez indiqué une taille inférieure à votre entrée au clavier, l'excédent sera considéré comme une commande par le shell, si cette commande est possible, aïe ! :-( On reste concentré sur ce que l'on fait, n'est-ce pas ?? :-)
Un exemple de ce qui peut arriver, j'avoue que j'y ai mis de la mauvaise volonté, :-).
Entrée dans la limite de la taille indiquée Entrée en dehors de la limite
:~$ od -Ax -a -N0x40
Attention ! Nom de fichier oublié, entrée par
défaut = stdin echo -e "\n\tOhé ! On dort ! :-)\n" #validation avec <Entrée> 000000 A t t e n t i o n sp ! sp N o m sp
000010 d e sp f i c h i e r sp o u b l i
000020 C ) , sp e n t r C ) e sp p a r sp
000030 d C ) f a u t sp = sp s t d i n sp
000040
:~$ echo -e "\n\tOhé ! On dort ! :-)\n"
Ohé ! On dort ! :-) :~$
Bah oui ! :-(, c'est fini... :-(. Vous reviendrez n'est-ce pas ?? :-)
Je vous aime déjà savez-vous ? Pensiez-vous que je vous laisserais partir sans quelques bonnes adresses ?
Non, non, je ne suis pas un ingrat ! :-) Jugez par vous-même :