Outils d'utilisateurs

Outils du Site


injection_elf

Ceci est une ancienne révision du document !


L'article n'est pas du tout fini. Ne pas le mettre dans le sommaire !

1. Introduction

Cette article va vous présenter comment injecter du code de manière statique dans un fichier ELF, que ce soit sur architecture 32 bits ou 64 bits, sous une distribution GNU/Linux.

2. Qu'est-ce que le format ELF ?

Afin de comprendre le fonctionnement de l'injection de code, il est nécessaire d'avoir une idée globale de ce qu'est le format ELF et de comment il fonctionne.

Les fichiers ELF (Executable and Linking Format) peuvent être des exécutables normaux (ls, dd, ponysay,…), des bibliothèques partagées (libcrypto.so, libglib.so,…), des fichiers core (core dump) et des fichiers objets (les fichiers .o générés pas les compilateurs qui n'ont pas encore été liés pour devenir des exécutables).

Un fichier ELF va être constitué d'un en-tête et soit d'une table d'en-tête de programme ou d'une table des en-têtes de sections, ou alors des deux. Dans notre cas, il est nécessaire de posséder la table d'en-tête de programme, de toute manière celle-ci est obligatoire pour les exécutables. En effet, cette partie va contenir les informations sur les sections du programme qui vont comprendre le code qui sera mappé dans l'espace d'adressage du programme.

ELF header

Voici la représentation de l'en-tête ELF (32 bits) sous la forme d'une structure C :

/usr/include/elf.h 65-85
/* The ELF file header.  This appears at the start of every ELF file.  */
 
#define EI_NIDENT (16)
 
typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;

Cette structure va nous donner différentes informations permettant de réaliser notre injection.

Tout d'abord, elle va contenir les informations concernant l'architecture utilisée (32bits ou 64bits) (e_ident), le codage utilisé (Little endian ou Big endian) (e_ident), le système d'exploitation auquel le binaire est destiné (e_ident), le type du fichier (exécutable, objet,…) (e_type) et la machine (ARM, x86_64,…) (e_machine). De cette manière, nous pourrons savoir si le fichier cible est bien un ELF, qu'il n'est pas mal formé et si nous devons injecter du code pour une architecture 32 bits ou 64 bits.

Elle va contenir le point d'entrée du programme (e_entry), c'est-à-dire, l'adresse virtuelle à laquelle le système va laisser la main au programme, cela va ainsi démarrer le processus (Ceci n'est pas le main() de votre programme !). Ce sera donc ce champ que nous devrons modifier pour rediriger le flux d'exécution à l'adresse du code que nous aurons injecté.

Elle va aussi contenir le décalage en octet de la table d'en-tête de programme (e_phoff) et le nombre d'entrées qu'elle contient (e_phnum), cela nous permettra de savoir si la table existe ou non.

Pour une description plus détaillé des différents champs, référez-vous au man elf

Program header

Voici la structure en C représentant un élément de la table d'en-tête de programme d'un ELF (32 bits) :

/usr/include/elf.h 537-561
/* Program segment header.  */
 
typedef struct
{
  Elf32_Word    p_type;                 /* Segment type */
  Elf32_Off     p_offset;               /* Segment file offset */
  Elf32_Addr    p_vaddr;                /* Segment virtual address */
  Elf32_Addr    p_paddr;                /* Segment physical address */
  Elf32_Word    p_filesz;               /* Segment size in file */
  Elf32_Word    p_memsz;                /* Segment size in memory */
  Elf32_Word    p_flags;                /* Segment flags */
  Elf32_Word    p_align;                /* Segment alignment */
} Elf32_Phdr;

3. Injection entre 2 segments LOAD

Nous allons maintenant voir comment il est possible d'insérer du code entre 2 segments LOAD sans changer la taille du fichier.

Liens externes

injection_elf.1341511159.txt.gz · Dernière modification: 2017/04/09 15:33 (modification externe)