(Courriels de diversion: <maigrirent@ajournerai-emettrez.com> <ressaisirent@smokings-haut-relief.com> <cotisent@cauterisons-allumettes.com> <vermeils@surmenaient-antidatees.com> <calibraient@pointus-connexe.com> <remportera@soustrairaient-couture.com> <informatises@rougissez-jalonnais.com> <planeriez@persevererent-moraine.com> <perte@mie-delicieux.com> <accoucherai@bilingues-deconcertera.com> )


Que se passe-t'il lorsqu'on lance un exécutable?

Le noyau détermine premièrement quel est le format de l'exécutable:
script qui sera traité par un interpréteur (premiers octets de "#!");
format spécial qui a été enrégistré auprès du module binfmt_misc [1];
exécutable ELF classique.

Supposons que ce soit un binaire ELF. On arrive dans binfmt_elf [2],
qui décode les entêtes de l'exécutable et lit notamment le contenu de
la section .interp du binaire. On peut utiliser objdump (qui fait
partie des binutils) pour afficher le contenu d'un binaire:

   ~$ objdump -j .interp --full-contents `which emacs`
   /usr/bin/emacs:     file format elf32-i386
   Contents of section .interp:
    80480d4 2f6c6962 2f6c642d 6c696e75 782e736f  /lib/ld-linux.so
    80480e4 2e3200                               .2. 

Le noyau passe la main à ld-linux.so.2, qui sera chargé de l'édition
dynamique de liens avec les bibliothèques partagées. Pour savoir
quelles sont les bibliothèques partagées utilisées par un exécutable,
utiliser ldd:

   ~$ ldd /usr/bin/emacs
           libXaw.so.6 => /usr/X11R6/lib/libXaw.so.6 (0x4000c000)
           libXmu.so.6 => /usr/X11R6/lib/libXmu.so.6 (0x40044000)
           libXt.so.6 => /usr/X11R6/lib/libXt.so.6 (0x40056000)
           libSM.so.6 => /usr/X11R6/lib/libSM.so.6 (0x400a0000)
           libICE.so.6 => /usr/X11R6/lib/libICE.so.6 (0x400a9000)
           libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x400be000)
           libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x400ca000)
           libncurses.so.3.4 => /lib/libncurses.so.3.4 (0x4016f000)
           libm.so.6 => /lib/libm.so.6 (0x401b4000)
           libc.so.6 => /lib/libc.so.6 (0x401cd000)
           /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

ld-linux cherchera les bibliothèques dans les répertoires donnés par
la variable d'environnement $LD_LIBRARY_PATH, puis dans les
répertoires listés dans /etc/ld.so, puis dans les chemins par défaut
/usr/lib et /lib.

Mais c'est pas encore terminé: la variable d'environnement $LD_PRELOAD
a un rôle spécial: les bibliothèques dynamiques qu'il contient seront
chargées _avant_ les autres, et les symbôles qu'elles exportent
pourront donc remplacer celles des bibliothèques standards.

Imaginons par exemple qu'on veuille remplacer la fonction time() de la
libc afin de vivre dans les années 1970:

   ~/tmp$ cat timetravel.c
   #include <sys/types.h>
   #include <sys/time.h>
   
   time_t time (time_t * ptr)
   {
     time_t t;
   
     t = 0;
     if(ptr) *ptr = 0;
     return t;
   }
   ~/tmp$ gcc -c -O -fPIC timetravel.c
   ~/tmp$ ld -shared timetravel.o -o timetravel.so
   ~/tmp$ date
   Tue Sep 14 13:56:22 CEST 1999
   ~/tmp$ export LD_PRELOAD=`pwd`/timetravel.so
   ~/tmp$ date
   Thu Jan  1 01:00:00 CET 1970


En utilisant dlopen() sur "/usr/lib/libc.so" dans timetravel.c on peut
accéder à la fonction time() d'origine, et donc exécuter des
applications dans une époque relative à la date courante.


[1] <URL:http://www.anatom.uni-tuebingen.de/~richi/linux/binfmt_misc.html>
[2] <URL:http://lxr.linux.no/source/fs/binfmt_elf.c>

-- 
The NSA is now funding research not only in cryptography, but in all areas of
advanced mathematics. If you'd like a circular describing these new research
opportunities, just pick up your phone, call your mother, and ask for one.

 _______________________________________________________________________
  Le CULTe sur le ouebe: http://savage.iut-blagnac.fr/