Introduction a LD_PRELOAD
|
23-06-2012, 13h43
(Modification du message : 08-12-2012, 17h21 par ark.)
Message : #1
|
|
ark
![]() Psyckomodo! ![]() ![]() ![]() ![]() ![]() Messages : 1,033 Sujets : 48 Points: 317 Inscription : Sep 2011 |
Introduction a LD_PRELOAD
Ce tuto va expliquer le fonctionnement de la variable d'environnement LD_PRELOAD sous GNU/Linux (probablement pareil sous Unix, mais j'ai pas testé :p)
1 - Qu'est ce que LD_PRELOAD Pour exécuter un programme sur un système, ce programme est avant tout recopié en mémoire. Cependant, il arrive très souvent qu'il utilise des libs externes, comme par exemple la libc, la libqt, ou bien d'autres encore... Prenons le cas d'un programme simple en C: Code C :
Ce code va écrire la longueur de la chaîne passée en paramètre. Vous pouvez le voir c'est très basique. Cependant, ce code fait 2 appels a des fonctions externes: printf et strlen. Au moment du lancement du programme, la première chose qui sera effectué sera de retrouver ces fonctions dans les libs installés. D'ailleurs, copiez ce code et compilez le. Un petit détail pour la compilation: utilisez l'option -fno-builtin de gcc sinon le compilo remplacera automatiquement l'appel a strlen par une builtin directement dans le code, ce qui ne permettra pas le fonctionnement de la suite de ce tuto. Puis, lancez le avec strace: strace ./prgm Vous pouvez voir ces lignes: Code : access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) Ici, on peut voir tous les accès fait aux libs, a la recherche des fonctions. Si la fonction n'existe pas, le programme ne pourra être lance, et une erreur surviendra. La fonction access() avec le flag F_OK permet de vérifier si le fichier existe (man 2 access). Si il existe, il est ensuite ouvert avec la fonction open() (voir man 2 open) puis la lib est lu avec la fonction read() (man 2 read ^^) Bon, voila pour le fonctionnement de base du lancement d'un programme ^^ LD_PRELOAD dans tout ca, et bien ca va nous permettre de set une (ou plusieurs) libs qui vont être load avant la recherche dans les libs systèmes. C'est peut etre pas très clair, mais en gros, ca permet de remplacer une fonction du système par une autre que vous aurez codé vous même. 2 - MISE EN PRATIQUE Bon, après avoir vu vite rapidement a quoi servait LD_PRELOAD, on va faire mumuse avec, parce que y a pas de raison qu'on le fasse pas. x) Gardez votre petit programme compilé de tout a l'heure de cote, on va en avoir besoin. Mais avant ça, ben moi je trouve que c'est un peu nase d'afficher juste un nombre correspondant au nombre de caractères... Et si on faisait en sorte que ca print: "chaîne = 6" plutot ? Facile, nan ? Ben bien sur. Mais sans toucher au code source, vous en pensez quoi ? ![]() Bon, tout ca pour revenir sur LD_PRELOAD. Rappelez vous, le soft appel strlen, et print le résultat avec printf. Ben on va cheater strlen pour qu'il print aussi la chaîne qui lui est passée en paramètre. Pour le faire, z'allez m'ouvrir un nouveau fichier C, et dedans vous allez copier coller le prototype de strlen qui se trouve dans le man, vous me virez ce ';' et vous rajoutez des accolades. Code C :
Bien ! Donc avec ca, et ben on doit retourner la longueur de la chaîne. Mais attention, si on utilise la vrai fonction strlen, c'est la notre qu'on va rappeler ! Récursivité infini = Segmentation fault. Ca serait dommage, parce que c'est pas le but. x) Du coup, comment on va faire ? Ben vous allez me coder un strlen en 4 lignes tas d'feignasse ! C'est fait ? Nan, parce que je vous file la solution si vous voulez, mais patientez un moment encore... Parce que cette fonction que vous codez, ben faites la en dehors de celle que vous avez ^^ Sinon, meme problème, récursivité inf... Code C :
Voila ! Bon, ben pour print, c'est facile ! Mais... On va juste pas utiliser printf. Pourquoi ? Ben parce que printf fait des appels a strlen. RÉCURSIVITÉ INFINIE AGAIN ! Comment on fait ? ben write(1, s, my_strlen(s)); Pourquoi utiliser write() ? Alors pour 2 raisons. La première, c'est que write() est une fonction qui réalise un appel système au niveau du kernel, c'est donc une fonction que l'on pourrait qualifier de "basique", en effet, elle ne fait en aucun cas appel a d'autres fonctions (comme par exemple strlen()). Et la deuxième raison, c'est qu'on lui donne directement la longueur de la chaîne passé en paramètre, d'ou le strlen(s) en 3em paramètre. Le premier paramètre est un file descriptor (fd), le 1 correspond a la sortie standard, c'est a dire la ou est affiché le texte. Pour plus de détail, allez voir le man 2 write(). (lisez les mans, c'est bon pour la santé ! ) Et voila ! Sauf que la ca va etre moche un peu... rajoutez un write(1, " = ", 3); juste en dessous du premier write, et c'est good ! man write pour ceux qui savent pas comment l’utiliser hein ![]() code final: Code C :
Compilez ensuite ce fichier de la maniere suivante: gcc -fPIC -shared lib.c -o lib.so lib.c étant le fichier que vous venez de coder. L'option -shared sert a dire a gcc que vous compilez une lib partagée, en '.so' donc. (Pour -fPIC, je sais pas, mais il pète une erreur sinon xD) Pour charger notre lib.so au lancement du prog, on va faire simplement: env LD_PRELOAD="./lib.so" ./prog argument Observez le résultat ![]() Voila, c'etait une petite introduction a l'utilisation de LD_PRELOAD. Bon, maintenant qu'on sait faire ca, imaginez un programme qui stocke un mot de passe dans une zone mémoire. Imaginez ensuite que ce mot de passe soit free() a la fin, ou mieux, imaginez que le programme fasse un strcmp dessus... ![]() Voila voila, je vous laisse imaginer tout ce que l'ont peux faire avec ca ! Questions ? Commentaires ? Critiques ? Je prends tout ! ![]() |
|
Messages dans ce sujet |
Introduction a LD_PRELOAD - par Ark - 23-06-2012, 13h43
RE: Introduction a LD_PRELOAD - par spin - 23-06-2012, 14h42
RE: Introduction a LD_PRELOAD - par Ark - 23-06-2012, 15h16
RE: Introduction a LD_PRELOAD - par supersnail - 23-06-2012, 16h35
RE: Introduction a LD_PRELOAD - par Ark - 23-06-2012, 17h32
RE: Introduction a LD_PRELOAD - par Dobry - 26-06-2012, 17h39
RE: Introduction a LD_PRELOAD - par spin - 26-06-2012, 18h05
RE: Introduction a LD_PRELOAD - par Dobry - 26-06-2012, 18h50
RE: Introduction a LD_PRELOAD - par spin - 26-06-2012, 19h17
RE: Introduction a LD_PRELOAD - par spin - 28-06-2012, 12h36
RE: Introduction a LD_PRELOAD - par Ark - 28-06-2012, 13h42
|
Sujets apparemment similaires… | |||||
Sujet | Auteur | Réponses | Affichages | Dernier message | |
[Tutoriel] Cacher un service derrière un autre avec LD_PRELOAD | b0fh | 3 | 709 |
30-11-2016, 00h06 Dernier message: ZeR0-@bSoLu |
Utilisateur(s) parcourant ce sujet : 1 visiteur(s)