Relro
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 सबमिट करें।
Relro
RELRO का मतलब है Relocation Read-Only और यह एक ऐसा उपाय है जो लिंकर्स (ld
) द्वारा लागू किया जाता है जो ELF के डेटा सेगमेंट के एक उपसमुच्चय को सभी पुनर्स्थापनों के लागू होने के बाद पढ़ने के लिए केवल बनाता है। इसका लक्ष्य एक हमलावर को GOT (Global Offset Table) या अन्य पुनर्स्थापन-संबंधित तालिकाओं में प्रविष्टियों को ओवरराइट करने से रोकना है जो प्रोग्राम निष्पादन के दौरान डेरिफरेंस की जाती हैं (जैसे __fini_array
)।
आधुनिक लिंकर्स RELRO को GOT (और कुछ अन्य अनुभागों) को .bss से पहले रखने के लिए पुनः क्रमबद्ध करके लागू करते हैं और – सबसे महत्वपूर्ण – एक समर्पित PT_GNU_RELRO
सेगमेंट बनाकर जो गतिशील लोडर द्वारा पुनर्स्थापनों को लागू करने के बाद R–X
के रूप में फिर से मैप किया जाता है। परिणामस्वरूप, .bss में सामान्य बफर ओवरफ्लो अब GOT तक नहीं पहुँच सकते और मनमाने-लिखाई प्राइमिटिव का उपयोग RELRO-सुरक्षित पृष्ठ के अंदर स्थित फ़ंक्शन पॉइंटर्स को ओवरराइट करने के लिए नहीं किया जा सकता है।
लिंकर्स द्वारा उत्पन्न होने वाले दो स्तरों की सुरक्षा हैं:
Partial RELRO
- ध्वज
-Wl,-z,relro
(या सीधेld
को कॉल करते समय केवल-z relro
) के साथ उत्पन्न। - केवल GOT का गैर-PLT भाग (जो डेटा पुनर्स्थापनों के लिए उपयोग किया जाता है) पढ़ने के लिए केवल सेगमेंट में रखा जाता है। अनुभाग जो रन-टाइम पर संशोधित करने की आवश्यकता होती है – सबसे महत्वपूर्ण .got.plt जो lazy binding का समर्थन करता है – लिखने योग्य रहते हैं।
- इसलिए, एक मनमाना लिखाई प्राइमिटिव अभी भी PLT प्रविष्टि को ओवरराइट करके निष्पादन प्रवाह को पुनर्निर्देशित कर सकता है (या ret2dlresolve करके)।
- प्रदर्शन प्रभाव नगण्य है और इसलिए लगभग हर वितरण वर्षों से कम से कम Partial RELRO के साथ पैकेज भेज रहा है (यह 2016 से GCC/Binutils का डिफ़ॉल्ट है)।
Full RELRO
- दोनों ध्वज
-Wl,-z,relro,-z,now
(जिसे-z relro -z now
भी कहा जाता है) के साथ उत्पन्न।-z now
गतिशील लोडर को सभी प्रतीकों को पहले से हल करने के लिए मजबूर करता है (eager binding) ताकि .got.plt को फिर से लिखने की आवश्यकता न हो और इसे सुरक्षित रूप से पढ़ने के लिए केवल मैप किया जा सके। - पूरा GOT, .got.plt, .fini_array, .init_array, .preinit_array और कुछ अतिरिक्त आंतरिक glibc तालिकाएँ पढ़ने के लिए केवल
PT_GNU_RELRO
सेगमेंट के अंदर समाप्त होती हैं। - मापने योग्य स्टार्ट-अप ओवरहेड जोड़ता है (सभी गतिशील पुनर्स्थापनों को लॉन्च पर संसाधित किया जाता है) लेकिन कोई रन-टाइम ओवरहेड नहीं।
2023 से कई मुख्यधारा के वितरण ने पूर्ण RELRO डिफ़ॉल्ट के साथ सिस्टम टूल-चेन (और अधिकांश पैकेज) को संकलित करने के लिए स्विच किया है – जैसे Debian 12 “bookworm” (dpkg-buildflags 13.0.0) और Fedora 35+। एक पेंटेस्टर के रूप में, आपको इसलिए उन बाइनरी का सामना करने की उम्मीद करनी चाहिए जहाँ हर GOT प्रविष्टि पढ़ने के लिए केवल है।
How to Check the RELRO status of a binary
$ checksec --file ./vuln
[*] '/tmp/vuln'
Arch: amd64-64-little
RELRO: Full
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
checksec
(भाग pwntools और कई वितरणों का) ELF
हेडर को पार्स करता है और सुरक्षा स्तर प्रिंट करता है। यदि आप checksec
का उपयोग नहीं कर सकते, तो readelf
पर निर्भर करें:
# Partial RELRO → PT_GNU_RELRO is present but BIND_NOW is *absent*
$ readelf -l ./vuln | grep -E "GNU_RELRO|BIND_NOW"
GNU_RELRO 0x0000000000600e20 0x0000000000600e20
# Full RELRO → PT_GNU_RELRO *and* the DF_BIND_NOW flag
$ readelf -d ./vuln | grep BIND_NOW
0x0000000000000010 (FLAGS) FLAGS: BIND_NOW
यदि बाइनरी चल रही है (जैसे कि एक सेट-यूआईडी रूट हेल्पर), तो आप अभी भी निष्पादन योग्य को /proc/$PID/exe
के माध्यम से निरीक्षण कर सकते हैं:
readelf -l /proc/$(pgrep helper)/exe | grep GNU_RELRO
अपने कोड को संकलित करते समय RELRO सक्षम करना
# GCC example – create a PIE with Full RELRO and other common hardenings
$ gcc -fPIE -pie -z relro -z now -Wl,--as-needed -D_FORTIFY_SOURCE=2 main.c -o secure
-z relro -z now
GCC/clang (के बाद -Wl,
) और ld के लिए सीधे काम करता है। CMake 3.18+ का उपयोग करते समय, आप अंतर्निहित प्रीसेट के साथ पूर्ण RELRO का अनुरोध कर सकते हैं:
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) # LTO
set(CMAKE_ENABLE_EXPORTS OFF)
set(CMAKE_BUILD_RPATH_USE_ORIGIN ON)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,relro,-z,now")
Bypass Techniques
RELRO स्तर | सामान्य प्राइमिटिव | संभावित शोषण तकनीकें |
---|---|---|
None / Partial | मनमाना लिखना | 1. .got.plt प्रविष्टि को ओवरराइट करें और निष्पादन को पिवट करें। 2. ret2dlresolve – एक लिखने योग्य खंड में नकली Elf64_Rela और Elf64_Sym बनाएं और _dl_runtime_resolve को कॉल करें।3. .fini_array / atexit() सूची में फ़ंक्शन पॉइंटर्स को ओवरराइट करें। |
Full | GOT केवल पढ़ने के लिए है | 1. अन्य लिखने योग्य कोड पॉइंटर्स (C++ vtables, __malloc_hook < glibc 2.34, __free_hook , कस्टम .data सेक्शन में कॉलबैक, JIT पृष्ठ) की तलाश करें।2. libc को लीक करने और SROP/ROP into libc करने के लिए सापेक्ष पढ़ने प्राइमिटिव का दुरुपयोग करें। 3. DT_RPATH/ LD_PRELOAD के माध्यम से एक धोखेबाज़ साझा वस्तु इंजेक्ट करें (यदि वातावरण हमलावर द्वारा नियंत्रित है) या ld_audit ।4. GOT को छुए बिना नियंत्रण प्रवाह को मोड़ने के लिए फॉर्मेट-स्ट्रिंग या आंशिक पॉइंटर ओवरराइट का शोषण करें। |
💡 पूर्ण RELRO के साथ भी लोड की गई साझा लाइब्रेरी (जैसे libc स्वयं) का केवल आंशिक RELRO है क्योंकि उन वस्तुओं को पहले से ही मैप किया गया है जब लोडर पुनर्स्थापनाएं लागू करता है। यदि आपको एक मनमाना लिखने का प्राइमिटिव मिलता है जो किसी अन्य साझा वस्तु के पृष्ठों को लक्षित कर सकता है, तो आप अभी भी libc के GOT प्रविष्टियों या
__rtld_global
स्टैक को ओवरराइट करके निष्पादन को पिवट कर सकते हैं, यह एक तकनीक है जिसका नियमित रूप से आधुनिक CTF चुनौतियों में शोषण किया जाता है।
वास्तविक दुनिया का बायपास उदाहरण (2024 CTF – pwn.college “enlightened”)
चुनौती पूर्ण RELRO के साथ आई। शोषण ने एक off-by-one का उपयोग किया ताकि एक हीप चंक के आकार को भ्रष्ट किया जा सके, tcache poisoning
के साथ libc को लीक किया, और अंततः __free_hook
(RELRO खंड के बाहर) को कोड निष्पादन प्राप्त करने के लिए एक एक-गैजेट के साथ ओवरराइट किया। कोई GOT लिखने की आवश्यकता नहीं थी।
हालिया अनुसंधान और कमजोरियाँ (2022-2025)
- glibc 2.40
__malloc_hook
/__free_hook
को अप्रचलित करता है (2025) – अधिकांश आधुनिक हीप शोषण जो इन प्रतीकों का दुरुपयोग करते थे, अबrtld_global._dl_load_jump
या C++ अपवाद तालिकाओं जैसे वैकल्पिक वेक्टर पर पिवट करना चाहिए। चूंकि हुक RELRO के बाहर रहते हैं, उनकी हटाने से पूर्ण RELRO बायपास की कठिनाई बढ़ जाती है। - Binutils 2.41 “max-page-size” सुधार (2024) – एक बग ने RELRO खंड के अंतिम कुछ बाइट्स को कुछ ARM64 निर्माणों पर लिखने योग्य डेटा के साथ एक पृष्ठ साझा करने की अनुमति दी, जिससे एक छोटा RELRO गैप बना जो
mprotect
के बाद लिखा जा सकता था। अपस्ट्रीम अबPT_GNU_RELRO
को पृष्ठ सीमाओं के साथ संरेखित करता है, उस किनारे के मामले को समाप्त करता है।
संदर्भ
- Binutils दस्तावेज़ –
-z relro
,-z now
औरPT_GNU_RELRO
- “RELRO – पूर्ण, आंशिक और बायपास तकनीकें” – ब्लॉग पोस्ट @ wolfslittlered 2023
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 सबमिट करें।