Variables Non Initialisées

Reading time: 4 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)

Soutenir HackTricks

Informations de Base

L'idée principale ici est de comprendre ce qui se passe avec les variables non initialisées car elles auront la valeur qui était déjà dans la mémoire qui leur a été assignée. Exemple :

  • Fonction 1 : initializeVariable : Nous déclarons une variable x et lui assignons une valeur, disons 0x1234. Cette action est semblable à la réservation d'un emplacement en mémoire et à la mise d'une valeur spécifique dedans.
  • Fonction 2 : useUninitializedVariable : Ici, nous déclarons une autre variable y mais ne lui assignons aucune valeur. En C, les variables non initialisées ne sont pas automatiquement mises à zéro. Au lieu de cela, elles conservent la dernière valeur qui a été stockée à leur emplacement mémoire.

Lorsque nous exécutons ces deux fonctions séquentiellement :

  1. Dans initializeVariable, x se voit assigner une valeur (0x1234), qui occupe une adresse mémoire spécifique.
  2. Dans useUninitializedVariable, y est déclarée mais n'a pas de valeur assignée, donc elle prend l'emplacement mémoire juste après x. En ne l'initialisant pas, y finit par "hériter" de la valeur du même emplacement mémoire utilisé par x, car c'est la dernière valeur qui y était.

Ce comportement illustre un concept clé en programmation bas niveau : La gestion de la mémoire est cruciale, et les variables non initialisées peuvent conduire à un comportement imprévisible ou à des vulnérabilités de sécurité, car elles peuvent contenir involontairement des données sensibles laissées en mémoire.

Les variables de pile non initialisées pourraient poser plusieurs risques de sécurité tels que :

  • Fuite de Données : Des informations sensibles telles que des mots de passe, des clés de chiffrement ou des détails personnels peuvent être exposées si elles sont stockées dans des variables non initialisées, permettant aux attaquants de potentiellement lire ces données.
  • Divulgation d'Informations : Le contenu des variables non initialisées pourrait révéler des détails sur la disposition mémoire du programme ou ses opérations internes, aidant les attaquants à développer des exploits ciblés.
  • Crashes et Instabilité : Les opérations impliquant des variables non initialisées peuvent entraîner un comportement indéfini, conduisant à des plantages de programme ou à des résultats imprévisibles.
  • Exécution de Code Arbitraire : Dans certains scénarios, les attaquants pourraient exploiter ces vulnérabilités pour altérer le flux d'exécution du programme, leur permettant d'exécuter du code arbitraire, ce qui pourrait inclure des menaces d'exécution de code à distance.

Exemple

c
#include <stdio.h>

// Function to initialize and print a variable
void initializeAndPrint() {
int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
}

// Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() {
int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
}

int main() {
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");

// First, call the function that initializes its variable
initializeAndPrint();

// Then, call the function that has an uninitialized variable
demonstrateUninitializedVar();

return 0;
}

Comment cela fonctionne :

  • initializeAndPrint Fonction : Cette fonction déclare une variable entière initializedVar, lui assigne la valeur 100, puis imprime à la fois l'adresse mémoire et la valeur de la variable. Cette étape est simple et montre comment se comporte une variable initialisée.
  • demonstrateUninitializedVar Fonction : Dans cette fonction, nous déclarons une variable entière uninitializedVar sans l'initialiser. Lorsque nous tentons d'imprimer sa valeur, la sortie peut afficher un nombre aléatoire. Ce nombre représente les données qui étaient précédemment à cet emplacement mémoire. Selon l'environnement et le compilateur, la sortie réelle peut varier, et parfois, par sécurité, certains compilateurs peuvent automatiquement initialiser les variables à zéro, bien que cela ne doive pas être considéré comme une garantie.
  • main Fonction : La fonction main appelle les deux fonctions ci-dessus en séquence, démontrant le contraste entre une variable initialisée et une variable non initialisée.

Exemple ARM64

Cela ne change pas du tout en ARM64 car les variables locales sont également gérées dans la pile, vous pouvez vérifier cet exemple où cela est montré.

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)

Soutenir HackTricks