अनप्रारम्भित वेरिएबल्स
Tip
AWS हैकिंग सीखें और अभ्यास करें:
HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें:HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
बुनियादी जानकारी
मुख्य विचार यह समझना है कि अनप्रारम्भित वेरिएबल्स का क्या होता है क्योंकि उनका मान उस मेमोरी में पहले मौजूद मान को ही ले लेता है जिसे उन्हें असाइन किया गया था। उदाहरण:
- Function 1:
initializeVariable: हम एक वेरिएबलxघोषित करते हैं और उसे एक मान देते हैं, उदाहरण के लिए0x1234। यह कार्रवाई मेमोरी में एक जगह रिज़र्व करने और उसमें एक विशेष मान रखने के समान है। - Function 2:
useUninitializedVariable: यहाँ हम एक और वेरिएबलyघोषित करते हैं लेकिन उसे कोई मान नहीं देते। C में, अनप्रारम्भित वेरिएबल्स अपने आप ज़ीरो पर सेट नहीं होते। इसके बजाय, वे अपनी मेमोरी लोकेशन पर आख़िरी बार जो मान स्टोर था वही बनाए रखते हैं।
जब हम इन दोनों फंक्शनों को क्रमिक रूप से चलाते हैं:
initializeVariableमें,xको एक मान (0x1234) असाइन किया जाता है, जो एक विशिष्ट मेमोरी एड्रेस घेरता है।useUninitializedVariableमें,yघोषित होता है पर किसी मान से असाइन नहीं होता, इसलिए यहxके ठीक बाद वाली मेमोरी स्पॉट ले लेता है।yको इनिशियलाइज़ न करने के कारण, यह उसी मेमोरी लोकेशन का पिछला मान “इनहेरिट” कर लेता है, क्योंकि वही वहाँ आख़िरी बार मौजूद था।
यह व्यवहार लो-लेवल प्रोग्रामिंग में एक महत्वपूर्ण अवधारणा दर्शाता है: मेमोरी प्रबंधन अत्यंत महत्वपूर्ण है, और अनप्रारम्भित वेरिएबल्स अनपेक्षित व्यवहार या सुरक्षा कमजोरियों का कारण बन सकते हैं, क्योंकि वे अनजाने में मेमोरी में छोड़ी गई संवेदनशील जानकारी धारण कर सकते हैं।
अनप्रारम्भित स्टैक वेरिएबल्स कई सुरक्षा जोखिम पैदा कर सकते हैं जैसे:
- Data Leakage: संवेदनशील जानकारी जैसे पासवर्ड, एन्क्रिप्शन कीज़, या व्यक्तिगत विवरण अनप्रारम्भित वेरिएबल्स में मौजूद होने पर उजागर हो सकते हैं, जिससे attackers संभवतः इन डेटा को पढ़ सकें।
- सूचना का प्रकटीकरण (Information Disclosure): अनप्रारम्भित वेरिएबल्स की सामग्री प्रोग्राम की मेमोरी लेआउट या आंतरिक कार्यप्रणाली के बारे में संकेत दे सकती है, जिससे attackers लक्षित exploit विकसित करने में मदद मिल सकती है।
- क्रैश और अस्थिरता (Crashes and Instability): अनप्रारम्भित वेरिएबल्स के साथ संचालन अपरिभाषित व्यवहार का कारण बन सकता है, जिससे प्रोग्राम क्रैश या अनपेक्षित परिणाम हो सकते हैं।
- Arbitrary Code Execution: कुछ परिस्थितियों में, attackers इन कमजोरियों का लाभ उठाकर प्रोग्राम के execution flow को बदल सकते हैं, जिससे वे arbitrary code execute कर सकें, जिसमें remote code execution के खतरे शामिल हो सकते हैं।
उदाहरण
#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;
}
How This Works:
initializeAndPrintFunction: यह फ़ंक्शन एक integer वेरिएबलinitializedVarघोषित करता है, उसे मान100असाइन करता है, और फिर वेरिएबल का memory address और value दोनों प्रिंट करता है। यह चरण सरल है और दिखाता है कि एक initialized वेरिएबल कैसे व्यवहार करता है।demonstrateUninitializedVarFunction: इस फ़ंक्शन में हम एक integer वेरिएबलuninitializedVarबिना initialize किए घोषित करते हैं। जब हम इसका मान प्रिंट करने का प्रयास करते हैं, तो आउटपुट में एक यादृच्छिक नंबर दिख सकता है। यह संख्या उस मेमोरी लोकेशन पर पहले मौजूद डेटा का प्रतिनिधित्व करती है। वातावरण और compiler के अनुसार वास्तविक आउटपुट भिन्न हो सकता है, और कभी-कभी सुरक्षा के लिए कुछ compilers वेरिएबल्स को अपने आप शून्य पर initialize कर सकते हैं, हालांकि इस पर भरोसा नहीं किया जाना चाहिए।mainFunction:mainफ़ंक्शन ऊपर दिए गए दोनों फ़ंक्शन्स को क्रमशः कॉल करता है, जिससे एक initialized वेरिएबल और एक uninitialized वेरिएबल के बीच का अंतर स्पष्ट होता है।
Practical exploitation patterns (2024–2025)
क्लासिक “read-before-write” bug अभी भी प्रासंगिक है क्योंकि आधुनिक mitigations (ASLR, canaries) अक्सर secrecy पर निर्भर करते हैं। सामान्य attack surfaces:
- Partially initialized structs copied to userland: Kernel या drivers अक्सर केवल length field को
memsetकरते हैं और फिरcopy_to_user(&u, &local_struct, sizeof(local_struct))करते हैं। Padding और unused fields stack canary halves, saved frame pointers या kernel pointers को leak कर देते हैं। यदि struct में function pointer है, उसे uninitialized छोड़ने से बाद में reuse पर controlled overwrite की अनुमति भी मिल सकती है। - Uninitialized stack buffers reused as indexes/lengths: एक uninitialized
size_t len;जिसका उपयोगread(fd, buf, len)की सीमा निर्धारित करने के लिए किया जाए, attackers को out-of-bounds reads/writes दे सकता है या size checks को bypass कर सकता है जब stack slot में पहले के कॉल की वजह से बड़ी value बनी हुई हो। - Compiler-added padding: भले ही व्यक्तिगत members initialize हों, उनके बीच के implicit padding bytes initialize नहीं होते। पूरे struct को userland में copy करने पर padding leak हो जाती है जो अक्सर prior stack content (canaries, pointers) रखती है।
- ROP/Canary disclosure: यदि कोई फ़ंक्शन debugging के लिए स्थानीय struct को stdout पर copy करता है, तो uninitialized padding stack canary को reveal कर सकता है जिससे बाद में stack overflow exploitation बिना brute-force के संभव हो जाता है।
Minimal PoC pattern to detect such issues during review:
struct msg {
char data[0x20];
uint32_t len;
};
ssize_t handler(int fd) {
struct msg m; // never fully initialized
m.len = read(fd, m.data, sizeof(m.data));
// later debug helper
write(1, &m, sizeof(m)); // leaks padding + stale stack
return m.len;
}
निवारक उपाय और compiler विकल्प (बायपास करते समय ध्यान रखें)
- Clang/GCC auto-init: हाल के toolchains
-ftrivial-auto-var-init=zeroया-ftrivial-auto-var-init=patternएक्सपोज़ करते हैं, जो फंक्शन एंट्री पर हर automatic (stack) वैरिएबल को zeros या एक poison pattern (0xAA / 0xFE) से भर देते हैं। यह अधिकांश uninitialized-stack info leaks बंद कर देता है और secrets को ज्ञात मानों में बदलकर exploitation को कठिन बना देता है। - Linux kernel hardening: Kernels जो
CONFIG_INIT_STACK_ALLया नएCONFIG_INIT_STACK_ALL_PATTERNके साथ बनाए गए हैं, function entry पर हर stack slot को zero/pattern-initialize करते हैं, उन canaries/pointers को मिटा देते हैं जो अन्यथा leak होते। ऐसे विकल्प सक्षम करके Clang-built kernels भेजने वाले distros देखें (6.8+ hardening configs में सामान्य)। - Opt-out attributes: Clang अब specific locals/structs पर
__attribute__((uninitialized))की अनुमति देता है ताकि performance-critical क्षेत्रों को uninitialized रखा जा सके, यहाँ तक कि जब global auto-init सक्षम हो। ऐसे annotations को ध्यान से देखें—वे अक्सर side channels के लिए जानबूझकर attack surface को चिह्नित करते हैं।
एक attacker के नजरिए से, यह जानना कि बाइनरी इन flags के साथ बनी थी या नहीं तय करता है कि stack-leak primitives viable हैं या आपको heap/data-section disclosures की ओर pivot करना होगा।
Finding uninitialized-stack bugs quickly
- Compiler diagnostics:
-Wall -Wextra -Wuninitialized(GCC/Clang) के साथ बिल्ड करें। C++ कोड के लिए,clang-tidy -checks=cppcoreguidelines-init-variablesकई मामलों को auto-fix कर के zero-init कर देता है और ऑडिट के दौरान मिस्ड locals को दिखाने में handy है। - Dynamic tools: Clang में
-fsanitize=memory(MSan) या Valgrind का--track-origins=yesfuzzing के दौरान uninitialized stack bytes के reads को reliably flag करते हैं। टेस्ट हार्नेस को इनसे instrument करें ताकि subtle padding leaks surface हों। - Grepping patterns: रिव्यू में उन
copy_to_user/writeकॉल्स को खोजें जो पूरे structs को भेजती हैं, या ऐसेmemcpy/sendजो केवल struct के हिस्से को सेट करते हैं पर stack डेटा को भेज देते हैं। खास ध्यान error paths पर रखें जहाँ initialization स्किप किया जाता है।
ARM64 Example
यह ARM64 में बिल्कुल भी नहीं बदलता क्योंकि local variables भी stack पर manage होते हैं, आप check this example में यह देख सकते हैं。
References
- CONFIG_INIT_STACK_ALL_PATTERN documentation
- GHSL-2024-197: GStreamer uninitialized stack variable leading to function pointer overwrite
Tip
AWS हैकिंग सीखें और अभ्यास करें:
HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें:HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।


