Auscultons les binaires et les librairies en strings
Public : débutant
Bonjour ,
Rassurez-vous, ici nous ne nous pencherons pas sur un petit morceau d'étoffe loué par les uns, décrié par les autres.
Ici, nous parlons de Linux.
Les strings dont il sera question dans cet article correspondent en fait à la commande éponyme : strings.
À quoi elle sert
La commande strings permet d'extraire des chaînes de texte humainement lisibles d'un exécutable, d'une libraire ou autres données binaires. Elle peut également traiter des fichiers compressés.
Et ce sont ces données que strings permet de débusquer, de traquer afin d'en connaître davantage.
Faisons connaissance avec strings
Ouvrons un terminal et tapotons-y* :
$ strings --help
Usage: strings [option(s)] [fichier(s)]
Afficher les chaînes imprimables des [fichier(s)] (stdin par défaut)
Les options sont :
-a - --all Scruter entièrement le fichier, pas seulement les sections de données [défaut]
-d --data Ne scruter que les sections de données du fichier
-f --print-file-name Afficher le nom du fichier avant chaque chaîne
-n <nombre> Localiser et afficher toute séquence d'au moins
--bytes=<nombre> <nombre> caractères affichables (par défaut 4).
-t --radix={o,d,x} Afficher la position de la chaîne en base 8, 10 ou 16
-o Un alias pour --radix=o
-T --target=<NOMBFD> Spécifier le format du fichier binaire
-e --encoding={s,S,b,l,B,L} Sélectionner la taille des caractères et le
système de poids fort ou faible :
s = 7-bits, S = 8-bits, {b,l} = 16-bits, {B,L} = 32-bits
--unicode={default|show|invalid|hex|escape|highlight}
-U {d|s|i|x|e|h} Spécifier comment traiter les caractères unicode encodés en UTF-8
-s --output-separator=<chaîne> Chaîne utilisée pour séparer les chaînes en sortie.
@<fichier> Lire les options à partir du <fichier>
-h --help Afficher l'aide-mémoire
-v -V --version Afficher la version du logiciel
strings: cibles supportées : elf32-i386 elf32-iamcu pei-i386 elf32-little elf32-big elf64-x86-64 elf32-x86-64 pe-x86-64 pei-x86-64 elf64-little elf64-big pe-bigobj-x86-64 pe-i386 pdb srec symbolsrec verilog tekhex binary ihex plugin trad-core
Rapporter toutes anomalies à <https://sourceware.org/bugzilla/>
*Selon la version, vous aurez peut-être une aide différente.
Passons à la pratique
Utilisons la commande brutalement.
Dans le terminal, toujours ouvert, pianotons :
$ strings /bin/ls
Lorsque la touche <Entrée> est enfoncée, les lignes défilent à vive allure : il y en a beaucoup.
Si vous faites défiler ces lignes, vous reconnaîtrez l'aide de la commande ls, entre autres.
Mais, ça demeure inexploitable. Il faut trouver un truc.
Et le truc, c'est d'envoyer le résultat de la commande strings à une autre commande grâce au 'pipe' (en pas français).
Essayons alternativement :
$ strings /bin/ls | head -20
/lib/ld-linux.so.2
%1{t
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
fgetfilecon
freecon
lgetfilecon
_IO_stdin_used
__stat64_time64
mempcpy
sigaction
__assert_fail
memmove
strchr
__ctype_toupper_loc
getpwuid
__gmtime64_r
optind
sigemptyset
Puis :
$ strings /bin/ls | tail -20
.gnu.version
.gnu.version_r
.rel.dyn
.rel.plt
.init
.plt.got
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.data.rel.ro
.dynamic
.got.plt
.data
.bss
.gnu_debugaltlink
.gnu_debuglink
Ces deux commandes permettent d'afficher les 20 première, puis les 20 dernières lignes retournées par la commande strings.
Vous, je sais pas, mais moi ça me convient encore moyennement.
Je vous propose une dernière commande un peu plus élaborée.
La voici :
$ strings /bin/ls | grep -Ei "[0-9]{1,3}\.[0-9]{1,3}|version"
LIBSELINUX_1.0
GLIBC_2.28
GLIBC_2.2
GLIBC_2.1.3
GLIBC_2.2.3
GLIBC_2.4
GLIBC_2.1
GLIBC_2.26
GLIBC_2.3.4
GLIBC_2.0
GLIBC_2.3
GLIBC_2.34
# slackware version of dircolors) are recognized but ignored.
sort_type != sort_version
time (-t), version (-v), extension (-X), width
-v natural sort of (version) numbers within text
--version output version information and exit
License GPLv3+: GNU GPL version 3 or later <%s>.
.gnu.version
.gnu.version_r
Grâce aux expressions régulières (regex), cette dernière commande extrait de l'extraction uniquement les chaînes qui contiennent de 1 à 3 chiffres suivis d'un point puis encore suivis de 1 à 3 chiffres, soit une chaîne qui pourrait correspondre à un n° de version OU les chaînes contenant le mot "version". L'option "i" nous affranchit du respect de la casse (minuscules/majuscules).
Évidemment, vous pouvez corser l'exercice en fonction de ce que vous cherchez.
On pourrait ne vouloir lister que les liens vers des sites internet, etc.
Pour ausculter une librairie, la syntaxe ne diffère pas.
Essayez avec :
$ strings /lib/libc.so.6 | grep -Ei "[0-9]{1,3}\.[0-9]{1,3}|version"
Bien sûr, il faudra peut-être adapter le chemin pour ce qui vous concerne.
Si nous voulons afficher les lignes avec un n° de version ET le mot "version", la syntaxe serait :
$ strings /lib/libc.so.6 | grep -Ei "[0-9]{1,3}\.[0-9]{1,3}.*version|version.*[0-9]{1,3}\.[0-9]{1,3}"
GNU C Library (Debian GLIBC 2.36-9+deb12u8) stable release version 2.36.
Compiled by GNU CC version 12.2.0.
Plus haut, j'ai annoncé que la commande strings opérait aussi sur les fichiers compressés.
Essayons !
Sur la ligne de commande du terminal, entrons :
$ strings mail.zip | head -10 ; strings mail.zip | tail -10
mail/UT
mail/article_envoyer_mail_pj_curl.txtUT
c4U2x,
;BQ%
a bt
1m.5!
>=yQAG
&Wz:D"
H9hU>
OT!o
mail/envoi_mail_curl_pj.txtUT
mail/exemple_mail_envoi.txtUT
mail/mail.txtUT
\WKXb
mail/mailo.txtUT
V7=eux
mail/modele_envoi_msg_avec_pj.emlUT
mail/modele_mail_texte_alternatif_pj.txtUT
mail/modele_mail_texte_simple_pj.txtUT
mail/status_imap.txtUT
Ainsi, nous avons affiché les 10 premières lignes et les 10 dernières retournées par la commande strings.
Nous voyons apparaître le nom de documents contenu dans l'archive, entre autres.
Essayons avec un document .pdf :
$ strings mtpaint-decoupe-texte.pdf | head -5
%PDF-1.5
3 0 obj
<< /Length 4 0 R
/Filter /FlateDecode
stream
Nous connaissons ainsi la version .pdf utilisée pour créer le document .pdf.
Il peut arriver que la commande ne fonctionne pas avec certains fichiers, tout simplement parce qu'ils ne sont pas pris en charge.
Le lien ci-dessous fournit d'autres exemples d'utilisation que je vous laisse découvrir.
Lien :
https://labex.io/fr/tutorials/linux-linux-strings-command-with-practical-examples-422934