← Retour à Reverse Engineering

Le Buffer Overflow dans .data

15 septembre 2026•8 min•Facile
Reverse EngineeringLinux

Le Buffer Overflow dans .data

On reste dans les buffers globaux et statiques, mais cette fois avec une valeur de départ non nulle. C'est la seule vraie différence avec .bss, et elle suffit à changer de section.

La section .data

Une variable globale ou statique initialisée avec une valeur non nulle à la déclaration ne va pas dans .bss, elle va dans .data. La distinction tient uniquement à ça, .bss accueille ce qui vaut zéro ou rien du tout au départ, .data accueille ce qui a une vraie valeur connue dès la compilation.

static int niveau = 1;

niveau a une valeur dès sa déclaration, elle vit donc dans .data, et cette valeur est stockée telle quelle dans le binaire.

Comment survient le Buffer Overflow

Le mécanisme est le même que pour .bss, une écriture non vérifiée dans un buffer de taille fixe qui déborde sur la variable voisine.

Exemple concret

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

static char nom[16] = "invite";
static int niveau = 1;

int main(void) {
    strcpy(nom, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
    printf("niveau = %d\n", niveau);
    return 0;
}

nom et niveau ont tous les deux une valeur à la déclaration, les deux vivent dans .data. Le strcpy(nom, ...) écrit 32 caractères dans un buffer de 16 octets, et déborde sur niveau.

$ ./data_overflow
niveau = 1094795585

niveau valait 1, il affiche maintenant 1094795585, soit 0x41414141 en décimal. Les octets A qui ont débordé de nom ont été réinterprétés comme un entier, et pas juste comme du texte écrasé.

Observer la corruption avec GDB

gdb ./data_overflow
(gdb) break main
(gdb) run
(gdb) print &nom
$1 = (char (*)[16]) 0x404040 <nom>
(gdb) print &niveau
$2 = (int *) 0x404050 <niveau>

niveau commence 16 octets après nom, les deux sont voisines. Après le strcpy, print niveau confirme la même valeur que celle affichée par le programme, 1094795585.

Identifier .data dans un binaire

nm ./data_overflow | grep -iE "nom|niveau"
0000000000404040 d nom
0000000000404050 d niveau

Le d (ou D pour un symbole global) indique une variable dans .data, à la différence du b/B vu pour .bss dans l'article précédent.

Comment l'éviter

La protection ne change pas d'un octet par rapport à .bss ou à n'importe quel autre buffer global, on contrôle la taille avant d'écrire dedans, avec strncpy ou équivalent. Tout ce qu'on a vu dans l'article précédent sur .bss s'applique ici sans aucune adaptation.

Conclusion

.data et .bss stockent le même genre de variables, la seule différence est la présence ou non d'une valeur initiale non nulle à la compilation. Le mécanisme du débordement, lui, reste rigoureusement identique, une écriture qui dépasse sa taille prévue vient toucher ce qui se trouve juste à côté, peu importe dans quelle section ce voisin se trouve.

Voir aussi d'autres catégories...

Ces thèmes pourraient aussi t'intéresser.