Les Buffer Overflow par Raphaël GERMON

La mémoire adressable

Voici un petit rappel sur le fonctionnement de la mémoire adressable sur un système d'exploitation.
Pour comprendre le dépassement de tampon et l'injection de shellcode, il est important de bien saisir le traitement d'une fonction en mémoire qui est décrit ci-dessous.

Rappels

schéma de la pile
Schéma de la mémoire adressable


Un programme en exécution (un processus) découpe la mémoire en zone distinces:
C'est les zones de pile d'excution (stack) et de tas (heap) qui nous intéressent. En effet, contrairement aux deux premières, les deux dernières zones sont dynamiques, c'est-à-dire que leur pourcentage d'utilisation et leur contenu varient tout au long de l'exécution d'un processus.

La zone de la pile d'exécution est utilisée par les fonctions (stockage des variables locales et passage des paramètres). Elle se comporte comme une pile, c'est-à-dire dernier entré, premier sorti. Les variables et les paramètres d'une fonction sont empilés avant le début de la fonction et dépilés à la fin de la fonction.

Une fonction est une suite d'instructions. Les instructions d'une fonction peuvent être exécutées (en informatique, on dit que la fonction est appelée) à partir de n'importe quel endroit d'un programme. À la fin de l'exécution des instructions de la fonction, l'exécution doit se continuer à l'instruction du programme qui suit l'instruction qui a appelé la fonction.

Pour permettre le retour au programme qui a appelé la fonction, l'instruction d'appel de la fonction (l'instruction call) enregistre l'adresse de retour dans la pile d'exécution. Lors de l'exécution de l'instruction ret qui marque la fin de la fonction, le processeur récupère l'adresse de retour qu'il a précédemment stockée dans la pile d'exécution et le processus peut continuer son exécution à cette adresse.
Plus précisément, le traitement d'une fonction inclut les étapes suivantes :
  1. l'empilage des paramètres de la fonction sur la pile d'exécution (avec l'instruction push) ;
  2. l'appel de la fonction (avec l'instruction call) ; cette étape déclenche la sauvegarde de l'adresse de retour de la fonction sur la pile d'exécution ;
  3. le début de la fonction qui inclut :
    1. la sauvegarde de l'adresse de la pile qui marque le début de l'enregistrement de l'état actuel du programme,
    2. l'allocation des variables locales dans la pile d'exécution ;
  4. l'exécution de la fonction ;
  5. la sortie de la fonction qui inclut la restauration du pointeur qui marquait le début de l'enregistrement de l'état du programme au moment de l'appel de la fonction,
  6. l'exécution de l'instruction ret qui indique la fin de la fonction et déclenche la récupération de l'adresse de retour et le branchement à cette adresse.