mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/common-binary-protections-and-bypas
This commit is contained in:
parent
58e092b727
commit
01a4c75662
@ -4,30 +4,96 @@
|
||||
|
||||
## Relro
|
||||
|
||||
**RELRO** का मतलब है **Relocation Read-Only**, और यह बाइनरी में एक सुरक्षा विशेषता है जो **GOT (Global Offset Table)** ओवरराइट्स से संबंधित जोखिमों को कम करने के लिए उपयोग की जाती है। **RELRO** सुरक्षा के दो प्रकार हैं: (1) **Partial RELRO** और (2) **Full RELRO**। दोनों **GOT** और **BSS** को ELF फ़ाइलों से पुनर्व्यवस्थित करते हैं, लेकिन विभिन्न परिणामों और निहितार्थों के साथ। विशेष रूप से, वे **GOT** अनुभाग को **BSS** से _पहले_ रखते हैं। अर्थात, **GOT** के पते **BSS** से कम हैं, जिससे **BSS** में वेरिएबल्स को ओवरफ्लो करके **GOT** प्रविष्टियों को ओवरराइट करना असंभव हो जाता है (याद रखें कि मेमोरी में लिखना निम्न से उच्च पते की ओर होता है)।
|
||||
**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**
|
||||
लिंकर्स द्वारा उत्पन्न होने वाले **दो स्तरों** की सुरक्षा हैं:
|
||||
|
||||
**Partial RELRO** सुरक्षा को बढ़ाने के लिए एक सरल दृष्टिकोण अपनाता है बिना बाइनरी के प्रदर्शन पर महत्वपूर्ण प्रभाव डाले। Partial RELRO **.got को केवल पढ़ने योग्य बनाता है (GOT अनुभाग का गैर-PLT भाग)**। ध्यान रखें कि अनुभाग का बाकी हिस्सा (जैसे .got.plt) अभी भी लिखने योग्य है और, इसलिए, हमलों के अधीन है। यह **GOT** को **मनमाने लिखने** की कमजोरियों से दुरुपयोग करने से नहीं रोकता है।
|
||||
### Partial RELRO
|
||||
|
||||
नोट: डिफ़ॉल्ट रूप से, GCC बाइनरी को Partial RELRO के साथ संकलित करता है।
|
||||
* ध्वज `-Wl,-z,relro` (या सीधे `ld` को कॉल करते समय केवल `-z relro`) के साथ उत्पन्न।
|
||||
* केवल **GOT** का **गैर-PLT** भाग (जो डेटा पुनर्स्थापनों के लिए उपयोग किया जाता है) पढ़ने के लिए केवल सेगमेंट में रखा जाता है। अनुभाग जो रन-टाइम पर संशोधित करने की आवश्यकता होती है – सबसे महत्वपूर्ण **.got.plt** जो **lazy binding** का समर्थन करता है – लिखने योग्य रहते हैं।
|
||||
* इसलिए, एक **मनमाना लिखाई** प्राइमिटिव अभी भी PLT प्रविष्टि को ओवरराइट करके निष्पादन प्रवाह को पुनर्निर्देशित कर सकता है (या **ret2dlresolve** करके)।
|
||||
* प्रदर्शन प्रभाव नगण्य है और इसलिए **लगभग हर वितरण वर्षों से कम से कम Partial RELRO के साथ पैकेज भेज रहा है (यह 2016 से GCC/Binutils का डिफ़ॉल्ट है)**।
|
||||
|
||||
### **Full RELRO**
|
||||
### Full RELRO
|
||||
|
||||
**Full RELRO** सुरक्षा को बढ़ाता है **पूरे GOT (दोनों .got और .got.plt) और .fini_array** अनुभाग को पूरी तरह से **पढ़ने योग्य** बनाकर। एक बार जब बाइनरी शुरू होती है, तो सभी फ़ंक्शन पते GOT में हल और लोड होते हैं, फिर, GOT को पढ़ने योग्य के रूप में चिह्नित किया जाता है, प्रभावी रूप से रनटाइम के दौरान इसमें किसी भी संशोधन को रोकता है।
|
||||
* **दोनों** ध्वज `-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` सेगमेंट के अंदर समाप्त होती हैं।
|
||||
* मापने योग्य स्टार्ट-अप ओवरहेड जोड़ता है (सभी गतिशील पुनर्स्थापनों को लॉन्च पर संसाधित किया जाता है) लेकिन **कोई रन-टाइम ओवरहेड नहीं**।
|
||||
|
||||
हालांकि, Full RELRO के साथ व्यापार-निष्कर्ष प्रदर्शन और स्टार्टअप समय के संदर्भ में है। क्योंकि इसे GOT को पढ़ने योग्य के रूप में चिह्नित करने से पहले स्टार्टअप पर सभी गतिशील प्रतीकों को हल करने की आवश्यकता होती है, **Full RELRO सक्षम बाइनरी में लंबे लोड समय का अनुभव हो सकता है**। यह अतिरिक्त स्टार्टअप ओवरहेड ही कारण है कि Full RELRO सभी बाइनरी में डिफ़ॉल्ट रूप से सक्षम नहीं है।
|
||||
2023 से कई मुख्यधारा के वितरण ने **पूर्ण RELRO डिफ़ॉल्ट** के साथ **सिस्टम टूल-चेन** (और अधिकांश पैकेज) को संकलित करने के लिए स्विच किया है – जैसे **Debian 12 “bookworm” (dpkg-buildflags 13.0.0)** और **Fedora 35+**। एक पेंटेस्टर के रूप में, आपको इसलिए उन बाइनरी का सामना करने की उम्मीद करनी चाहिए जहाँ **हर GOT प्रविष्टि पढ़ने के लिए केवल है**।
|
||||
|
||||
यह देखना संभव है कि क्या Full RELRO एक बाइनरी में **सक्षम** है:
|
||||
---
|
||||
|
||||
## How to Check the RELRO status of a binary
|
||||
```bash
|
||||
readelf -l /proc/ID_PROC/exe | grep BIND_NOW
|
||||
$ checksec --file ./vuln
|
||||
[*] '/tmp/vuln'
|
||||
Arch: amd64-64-little
|
||||
RELRO: Full
|
||||
Stack: Canary found
|
||||
NX: NX enabled
|
||||
PIE: No PIE (0x400000)
|
||||
```
|
||||
`checksec` (भाग [pwntools](https://github.com/pwncollege/pwntools) और कई वितरणों का) `ELF` हेडर को पार्स करता है और सुरक्षा स्तर प्रिंट करता है। यदि आप `checksec` का उपयोग नहीं कर सकते, तो `readelf` पर निर्भर करें:
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
## Bypass
|
||||
|
||||
यदि Full RELRO सक्षम है, तो इसे बायपास करने का एकमात्र तरीका यह है कि कोई और तरीका खोजा जाए जिसे मनमाने निष्पादन के लिए GOT तालिका में लिखने की आवश्यकता न हो।
|
||||
```bash
|
||||
# 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`** के माध्यम से निरीक्षण कर सकते हैं:
|
||||
```bash
|
||||
readelf -l /proc/$(pgrep helper)/exe | grep GNU_RELRO
|
||||
```
|
||||
---
|
||||
|
||||
ध्यान दें कि **LIBC का GOT आमतौर पर Partial RELRO है**, इसलिए इसे मनमाने लिखने के साथ संशोधित किया जा सकता है। अधिक जानकारी के लिए [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
|
||||
## अपने कोड को संकलित करते समय RELRO सक्षम करना
|
||||
```bash
|
||||
# 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 का अनुरोध कर सकते हैं:
|
||||
```cmake
|
||||
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** प्रविष्टि को ओवरराइट करें और निष्पादन को पिवट करें।<br>2. **ret2dlresolve** – एक लिखने योग्य खंड में नकली `Elf64_Rela` और `Elf64_Sym` बनाएं और `_dl_runtime_resolve` को कॉल करें।<br>3. **.fini_array** / **atexit()** सूची में फ़ंक्शन पॉइंटर्स को ओवरराइट करें। |
|
||||
| Full | GOT केवल पढ़ने के लिए है | 1. **अन्य लिखने योग्य कोड पॉइंटर्स** (C++ vtables, `__malloc_hook` < glibc 2.34, `__free_hook`, कस्टम `.data` सेक्शन में कॉलबैक, JIT पृष्ठ) की तलाश करें।<br>2. libc को लीक करने और **SROP/ROP into libc** करने के लिए *सापेक्ष पढ़ने* प्राइमिटिव का दुरुपयोग करें।<br>3. **DT_RPATH**/`LD_PRELOAD` के माध्यम से एक धोखेबाज़ साझा वस्तु इंजेक्ट करें (यदि वातावरण हमलावर द्वारा नियंत्रित है) या **`ld_audit`**।<br>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
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user