# Hijack d'une fonction avec LD_PRELOAD sur GNU/Linux

description : Article sur comment créer un hijack / un détournement de fonction avec LD_PRELOAD sur GNU/Linux
categories : Hacking;
tags : Linux; C;

Hijack d'une fonction avec LD_PRELOAD sur GNU/Linux

Pour mieux comprendre cet article, je vous recommande de lire avant celui-ci : Création et utilisation des librairies en langage de programmation C

Introduction

Il existe plusieurs façons de produire un exécutable, l'une d'entre elle consiste à utiliser les librairies partagées.
Donc, à utiliser les fichiers ".so" sur GNU/Linux.

Pour connaître les librairies partagées dont dépend un exécutable, il existe l'outil ldd. Exemple :

1
2
3
4
5
6
7
8
$ ldd /bin/ls
	linux-vdso.so.1 (0x00007fffcdd8f000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f1fe406c000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1fe3e7b000)
	libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f1fe3df6000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1fe3df0000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f1fe40d3000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1fe3dcd000)

Nous pouvons voir ici les dépendances de l'exécutable ls ainsi que les adresses où seront mappées ces dépendances.

Hijack d'une fonction

Le therme hijack signifie ici : détournement.
Je vais donc expliquer comment détourner une fonction grâce à la variable d'environnement LD_PRELOAD.

Prenons un exemple qui vérifie la correspondance entre deux chaînes de caractères en utilisant la fonction strcmp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char passwd[] = "foobar";
    
    if (argc < 2)
    {
        printf("usage: %s <password>\n", argv[0]);
        
        return 0;
    }

    if (!strcmp(passwd, argv[1]))
    {
        printf("Good !\n");

        return 1;
    }

    printf("Wrong !\n");

    return 0;
}

Compilons :

$ gcc strcmp.c

Essayons :

$ ./a.out deadbeef
Wrong !

Cet exemple peut être attaqué en détournant la fonction strcmp pour utiliser une fonction qui renvoie toujours 0 signifiant que les deux chaînes de caractères sont égales.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <stdio.h>
#include <string.h>

int strcmp(const char *s1, const char *s2)
{
    printf("s1: %s\n", s1);
    printf("s2: %s\n", s2);

    return 0;
}

Je compile ce code en tant que librairie partagée :

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

L'attaque consiste maintenant à utiliser la variable d'envionnement LD_PRELOAD :

1
2
3
4
$ LD_PRELOAD="./hijack.so" ./a.out deadbeef
s1: foobar
s2: deadbeef
Good !

Nous pouvons donc voir que même si les deux chaînes de caractères ne correspondent pas, nous obtenons bien le message "Good !".

Cool!