Hook avec LD_PRELOAD

Published on Sunday, 06 January 2013 in Trick ; tagged with ld preload, unix, hook, bypass, trick ; text version

Comment hook une fonction standarde avec LD_PRELOAD

Futex m'a parlé il y a peu d'un trick unix qui m'était inconnu jusqu'alors : poser un hook avec LD_PRELOAD. Pour faire simple, LD_PRELOAD permet de charger une lib avec celles standardes. Cette méthode peut être utile si vous voulez modifier le comportement d'un programme de manière simple mais efficace. Pour cela, il suffit de créer une fausse lib contenant votre fonction maison ayant le même nom que celle que vous voulez hook et renseigner le chemin d'accès vers celle-ci dans la variable d'environnement LD_PRELOAD.

La méthode est applicable seulement si le programme cible a été compiler pour pouvoir utiliser des lib partagées. C'est généralement le cas puisque les fonctions standardes de C comme printf, strcmp, etc. sont contenues dans ce type de lib. Donc si la cible les utilise alors vous pouvez appliquer ce trick. Pour en être certain il suffit d'utiliser le tool file et de regarder si c'est le cas.

$ file example
example: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically
linked (uses shared libs), for GNU/Linux 2.6.32,
BuildID[sha1]=0x24a0e0e2aa5e5603263aa9f6e89d839dc1eb4090, not stripped

Mis en pratique

Je pense que le meilleur moyen de bien saisir l'affaire est de l'appliquer. Comme exemple je propose le programme suivant :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argv, char *argc[]) {
    if (argv < 2) {
        printf("need argument\n");
        return 0;
    }
    else {
        if (!strcmp(argc[1], "password"))
            printf("good job!\n");
        else
            printf("bad password!\n");
    }

    return 0;
}

Si on lance notre programme avec un argument quelconque, on obtient un joli bad password!.

$ ./example test
bad password!

Création de la fake lib

Notre but ici est de modifier le comportement de strcmp et bypasser la comparaison. On écrit alors une autre fonction strcmp qui retournera toujours 0 et affichera aussi les deux paramètres.

#include <stdio.h>

int strcmp(char *str1, char *str2) {
    printf("hook of strcmp\n");
    printf("str1: %s\n", str1);
    printf("str2: %s\n", str2);

    return 0;
}

On compile notre fake lib avec la commande suivante :

gcc -fPIC -shared fake_strcmp.c -o fake_strcmp.so

Il faut encore modifier la variable LD_PRELOAD pour la faire pointer vers notre lib fraichement compilée.

$ export LD_PRELOAD=./fake_strcmp.so

Relançons le programme d'exemple pour voir ce que ça donne :

$ ./example test
hook of strcmp
str1: test
str2: password
good job!

La comparaison faite par strcmp est bien bypassée. Le trick a été appliqué avec succès !


contactdepier.re License WTFPL2