Uninitialized Variables

Support HackTricks

Basic Information

Η βασική ιδέα εδώ είναι να κατανοήσουμε τι συμβαίνει με τις μη αρχικοποιημένες μεταβλητές καθώς θα έχουν την τιμή που ήταν ήδη στη μνήμη που τους έχει ανατεθεί. Παράδειγμα:

  • Function 1: initializeVariable: Δηλώνουμε μια μεταβλητή x και της αναθέτουμε μια τιμή, ας πούμε 0x1234. Αυτή η ενέργεια είναι παρόμοια με την κράτηση μιας θέσης στη μνήμη και την τοποθέτηση μιας συγκεκριμένης τιμής σε αυτήν.

  • Function 2: useUninitializedVariable: Εδώ, δηλώνουμε μια άλλη μεταβλητή y αλλά δεν της αναθέτουμε καμία τιμή. Στη C, οι μη αρχικοποιημένες μεταβλητές δεν ρυθμίζονται αυτόματα σε μηδέν. Αντίθετα, διατηρούν όποια τιμή ήταν τελευταία αποθηκευμένη στη θέση μνήμης τους.

Όταν εκτελούμε αυτές τις δύο συναρτήσεις διαδοχικά:

  1. Στην initializeVariable, η x ανατίθεται μια τιμή (0x1234), η οποία καταλαμβάνει μια συγκεκριμένη διεύθυνση μνήμης.

  2. Στην useUninitializedVariable, η y δηλώνεται αλλά δεν της ανατίθεται τιμή, οπότε καταλαμβάνει τη θέση μνήμης αμέσως μετά την x. Λόγω της μη αρχικοποίησης της y, καταλήγει να "κληρονομεί" την τιμή από την ίδια θέση μνήμης που χρησιμοποιήθηκε από την x, επειδή αυτή είναι η τελευταία τιμή που υπήρχε εκεί.

Αυτή η συμπεριφορά απεικονίζει μια βασική έννοια στον προγραμματισμό χαμηλού επιπέδου: Η διαχείριση μνήμης είναι κρίσιμη, και οι μη αρχικοποιημένες μεταβλητές μπορούν να οδηγήσουν σε απρόβλεπτη συμπεριφορά ή ευπάθειες ασφαλείας, καθώς μπορεί να κρατούν κατά λάθος ευαίσθητα δεδομένα που έχουν μείνει στη μνήμη.

Οι μη αρχικοποιημένες μεταβλητές στο στοίβα θα μπορούσαν να θέσουν αρκετούς κινδύνους ασφαλείας όπως:

  • Data Leakage: Ευαίσθητες πληροφορίες όπως κωδικοί πρόσβασης, κλειδιά κρυπτογράφησης ή προσωπικές λεπτομέρειες μπορεί να εκτεθούν αν αποθηκευτούν σε μη αρχικοποιημένες μεταβλητές, επιτρέποντας στους επιτιθέμενους να διαβάσουν αυτά τα δεδομένα.

  • Information Disclosure: Το περιεχόμενο των μη αρχικοποιημένων μεταβλητών μπορεί να αποκαλύψει λεπτομέρειες σχετικά με τη διάταξη μνήμης του προγράμματος ή τις εσωτερικές λειτουργίες, βοηθώντας τους επιτιθέμενους να αναπτύξουν στοχευμένες εκμεταλλεύσεις.

  • Crashes and Instability: Οι λειτουργίες που περιλαμβάνουν μη αρχικοποιημένες μεταβλητές μπορεί να οδηγήσουν σε μη καθορισμένη συμπεριφορά, προκαλώντας κρα crashes ή απρόβλεπτα αποτελέσματα.

  • Arbitrary Code Execution: Σε ορισμένα σενάρια, οι επιτιθέμενοι θα μπορούσαν να εκμεταλλευτούν αυτές τις ευπάθειες για να αλλάξουν τη ροή εκτέλεσης του προγράμματος, επιτρέποντάς τους να εκτελέσουν αυθαίρετο κώδικα, ο οποίος μπορεί να περιλαμβάνει απειλές εκτέλεσης απομακρυσμένου κώδικα.

Example

#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;
}

Πώς Λειτουργεί Αυτό:

  • initializeAndPrint Συνάρτηση: Αυτή η συνάρτηση δηλώνει μια ακέραια μεταβλητή initializedVar, της αναθέτει την τιμή 100 και στη συνέχεια εκτυπώνει τόσο τη διεύθυνση μνήμης όσο και την τιμή της μεταβλητής. Αυτό το βήμα είναι απλό και δείχνει πώς συμπ behaves μια αρχικοποιημένη μεταβλητή.

  • demonstrateUninitializedVar Συνάρτηση: Σε αυτή τη συνάρτηση, δηλώνουμε μια ακέραια μεταβλητή uninitializedVar χωρίς να την αρχικοποιήσουμε. Όταν προσπαθούμε να εκτυπώσουμε την τιμή της, η έξοδος μπορεί να δείξει έναν τυχαίο αριθμό. Αυτός ο αριθμός αντιπροσωπεύει οποιαδήποτε δεδομένα ήταν προηγουμένως σε αυτή τη διεύθυνση μνήμης. Ανάλογα με το περιβάλλον και τον μεταγλωττιστή, η πραγματική έξοδος μπορεί να διαφέρει, και μερικές φορές, για λόγους ασφαλείας, ορισμένοι μεταγλωττιστές μπορεί να αρχικοποιούν αυτόματα τις μεταβλητές σε μηδέν, αν και αυτό δεν θα πρέπει να θεωρείται δεδομένο.

  • main Συνάρτηση: Η main συνάρτηση καλεί και τις δύο παραπάνω συναρτήσεις διαδοχικά, δείχνοντας τη διαφορά μεταξύ μιας αρχικοποιημένης μεταβλητής και μιας μη αρχικοποιημένης.

Παράδειγμα ARM64

Αυτό δεν αλλάζει καθόλου στο ARM64 καθώς οι τοπικές μεταβλητές διαχειρίζονται επίσης στο στοίβα, μπορείτε να ελέγξετε αυτό το παράδειγμα όπου αυτό δείχνεται.

Υποστήριξη HackTricks

Last updated