mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/basic-stack-binary-exploitation-met
This commit is contained in:
parent
04c1b2bb91
commit
1827c92bdf
@ -1,4 +1,4 @@
|
||||
# ELF बुनियादी जानकारी
|
||||
# ELF मूल जानकारी
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -37,54 +37,70 @@ Segment Sections...
|
||||
07
|
||||
08 .init_array .fini_array .dynamic .got
|
||||
```
|
||||
पिछले प्रोग्राम में **9 प्रोग्राम हेडर** हैं, फिर, **सेगमेंट मैपिंग** यह दर्शाता है कि **प्रत्येक सेक्शन** किस प्रोग्राम हेडर (00 से 08 तक) में **स्थित है**।
|
||||
The previous program has **9 program headers**, then, the **segment mapping** indicates in which program header (from 00 to 08) **each section is located**.
|
||||
|
||||
### PHDR - प्रोग्राम हेडर
|
||||
### PHDR - Program HeaDeR
|
||||
|
||||
प्रोग्राम हेडर टेबल और मेटाडेटा को स्वयं शामिल करता है।
|
||||
Contains the program header tables and metadata itself.
|
||||
|
||||
### INTERP
|
||||
|
||||
बाइनरी को मेमोरी में लोड करने के लिए उपयोग करने के लिए लोडर का पथ दर्शाता है।
|
||||
Indicates the path of the loader to use to load the binary into memory.
|
||||
|
||||
> Tip: Statically linked or static-PIE binaries won’t have an `INTERP` entry. In those cases there is no dynamic loader involved, which disables techniques that rely on it (e.g., `ret2dlresolve`).
|
||||
|
||||
### LOAD
|
||||
|
||||
ये हेडर यह दर्शाने के लिए उपयोग किए जाते हैं कि **बाइनरी को मेमोरी में कैसे लोड किया जाए।**\
|
||||
प्रत्येक **LOAD** हेडर **मेमोरी** के एक क्षेत्र (आकार, अनुमतियाँ और संरेखण) को दर्शाता है और ELF **बाइनरी के बाइट्स को वहाँ कॉपी करने** का संकेत देता है।
|
||||
These headers are used to indicate **how to load a binary into memory.**\
|
||||
Each **LOAD** header indicates a region of **memory** (size, permissions and alignment) and indicates the bytes of the ELF **binary to copy in there**.
|
||||
|
||||
उदाहरण के लिए, दूसरा 0x1190 का आकार है, इसे 0x1fc48 पर स्थित होना चाहिए जिसमें पढ़ने और लिखने की अनुमतियाँ हैं और इसे 0xfc48 से 0x528 से भरा जाएगा (यह सभी आरक्षित स्थान को नहीं भरता)। यह मेमोरी सेक्शन को शामिल करेगी `.init_array .fini_array .dynamic .got .data .bss`।
|
||||
For example, the second one has a size of 0x1190, should be located at 0x1fc48 with permissions read and write and will be filled with 0x528 from the offset 0xfc48 (it doesn't fill all the reserved space). This memory will contain the sections `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
|
||||
### DYNAMIC
|
||||
|
||||
यह हेडर प्रोग्रामों को उनके पुस्तकालय निर्भरताओं से लिंक करने और पुनर्स्थापनाएँ लागू करने में मदद करता है। **`.dynamic`** सेक्शन की जांच करें।
|
||||
This header helps to link programs to their library dependencies and apply relocations. Check the **`.dynamic`** section.
|
||||
|
||||
### NOTE
|
||||
|
||||
यह बाइनरी के बारे में विक्रेता मेटाडेटा जानकारी संग्रहीत करता है।
|
||||
This stores vendor metadata information about the binary.
|
||||
|
||||
- On x86-64, `readelf -n` will show `GNU_PROPERTY_X86_FEATURE_1_*` flags inside `.note.gnu.property`. If you see `IBT` and/or `SHSTK`, the binary was built with CET (Indirect Branch Tracking and/or Shadow Stack). This impacts ROP/JOP because indirect branch targets must start with an `ENDBR64` instruction and returns are checked against a shadow stack. See the CET page for details and bypass notes.
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
|
||||
{{#endref}}
|
||||
|
||||
### GNU_EH_FRAME
|
||||
|
||||
स्टैक अनवाइंड टेबल के स्थान को परिभाषित करता है, जिसका उपयोग डिबगर्स और C++ अपवाद हैंडलिंग-रनटाइम फ़ंक्शंस द्वारा किया जाता है।
|
||||
Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions.
|
||||
|
||||
### GNU_STACK
|
||||
|
||||
स्टैक निष्पादन रोकथाम रक्षा की कॉन्फ़िगरेशन को शामिल करता है। यदि सक्षम है, तो बाइनरी स्टैक से कोड निष्पादित नहीं कर सकेगी।
|
||||
Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack.
|
||||
|
||||
- Check with `readelf -l ./bin | grep GNU_STACK`. To forcibly toggle it during tests you can use `execstack -s|-c ./bin`.
|
||||
|
||||
### GNU_RELRO
|
||||
|
||||
बाइनरी के RELRO (रिलोकेशन रीड-ओनली) कॉन्फ़िगरेशन को दर्शाता है। यह सुरक्षा प्रोग्राम के लोड होने के बाद और चलने से पहले मेमोरी के कुछ सेक्शनों (जैसे `GOT` या `init` और `fini` टेबल) को रीड-ओनली के रूप में चिह्नित करेगी।
|
||||
Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the `GOT` or the `init` and `fini` tables) after the program has loaded and before it begins running.
|
||||
|
||||
पिछले उदाहरण में यह 0x1fc48 पर 0x3b8 बाइट्स को रीड-ओनली के रूप में कॉपी कर रहा है जो सेक्शनों को प्रभावित करता है `.init_array .fini_array .dynamic .got .data .bss`।
|
||||
In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecting the sections `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
|
||||
ध्यान दें कि RELRO आंशिक या पूर्ण हो सकता है, आंशिक संस्करण **`.plt.got`** सेक्शन की सुरक्षा नहीं करता है, जिसका उपयोग **लेज़ी बाइंडिंग** के लिए किया जाता है और इसे पुस्तकालयों के पते को पहली बार खोजे जाने पर लिखने के लिए **लिखने की अनुमतियाँ** की आवश्यकता होती है।
|
||||
Note that RELRO can be partial or full, the partial version do not protect the section **`.plt.got`**, which is used for **lazy binding** and needs this memory space to have **write permissions** to write the address of the libraries the first time their location is searched.
|
||||
|
||||
> For exploitation techniques and up-to-date bypass notes, check the dedicated page:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
### TLS
|
||||
|
||||
TLS प्रविष्टियों की एक तालिका को परिभाषित करता है, जो थ्रेड-स्थानीय चर के बारे में जानकारी संग्रहीत करता है।
|
||||
Defines a table of TLS entries, which stores info about thread-local variables.
|
||||
|
||||
## सेक्शन हेडर
|
||||
## Section Headers
|
||||
|
||||
सेक्शन हेडर ELF बाइनरी का अधिक विस्तृत दृश्य प्रदान करते हैं।
|
||||
Section headers gives a more detailed view of the ELF binary
|
||||
```
|
||||
objdump lnstat -h
|
||||
|
||||
@ -149,14 +165,14 @@ CONTENTS, READONLY
|
||||
|
||||
### मेटा अनुभाग
|
||||
|
||||
- **स्ट्रिंग तालिका**: इसमें ELF फ़ाइल द्वारा आवश्यक सभी स्ट्रिंग्स होती हैं (लेकिन प्रोग्राम द्वारा वास्तव में उपयोग की जाने वाली नहीं)। उदाहरण के लिए, इसमें अनुभागों के नाम जैसे `.text` या `.data` होते हैं। और यदि `.text` स्ट्रिंग तालिका में ऑफ़सेट 45 पर है, तो यह **नाम** फ़ील्ड में संख्या **45** का उपयोग करेगा।
|
||||
- **स्ट्रिंग तालिका**: इसमें ELF फ़ाइल द्वारा आवश्यक सभी स्ट्रिंग्स होती हैं (लेकिन वे जो वास्तव में प्रोग्राम द्वारा उपयोग की जाती हैं)। उदाहरण के लिए, इसमें अनुभाग के नाम जैसे `.text` या `.data` होते हैं। और यदि `.text` स्ट्रिंग तालिका में ऑफ़सेट 45 पर है, तो यह **नाम** फ़ील्ड में संख्या **45** का उपयोग करेगा।
|
||||
- स्ट्रिंग तालिका का स्थान खोजने के लिए, ELF में स्ट्रिंग तालिका के लिए एक पॉइंटर होता है।
|
||||
- **सिंबल तालिका**: इसमें प्रतीकों के बारे में जानकारी होती है जैसे नाम (स्ट्रिंग तालिका में ऑफ़सेट), पता, आकार और प्रतीक के बारे में अधिक मेटाडेटा।
|
||||
|
||||
### मुख्य अनुभाग
|
||||
|
||||
- **`.text`**: प्रोग्राम को चलाने के लिए निर्देश।
|
||||
- **`.data`**: प्रोग्राम में एक परिभाषित मान के साथ वैश्विक चर।
|
||||
- **`.data`**: प्रोग्राम में परिभाषित मान के साथ वैश्विक चर।
|
||||
- **`.bss`**: वैश्विक चर जो अनियोजित छोड़ दिए गए हैं (या शून्य पर प्रारंभिक)। यहाँ के चर स्वचालित रूप से शून्य पर प्रारंभिक होते हैं, इसलिए बाइनरी में बेकार शून्य जोड़ने से रोका जाता है।
|
||||
- **`.rodata`**: स्थायी वैश्विक चर (पढ़ने के लिए केवल अनुभाग)।
|
||||
- **`.tdata`** और **`.tbss`**: जैसे .data और .bss जब थ्रेड-स्थानीय चर का उपयोग किया जाता है (`__thread_local` C++ में या `__thread` C में)।
|
||||
@ -194,6 +210,10 @@ Num: Value Size Type Bind Vis Ndx Name
|
||||
- **मान** (स्मृति में पता)
|
||||
- **आकार**
|
||||
|
||||
#### GNU प्रतीक संस्करणन (dynsym/dynstr/gnu.version)
|
||||
|
||||
आधुनिक glibc प्रतीक संस्करणों का उपयोग करता है। आप `.gnu.version` और `.gnu.version_r` में प्रविष्टियाँ देखेंगे और प्रतीक नाम जैसे `strlen@GLIBC_2.17`। गतिशील लिंककर्ता प्रतीक को हल करते समय एक विशिष्ट संस्करण की आवश्यकता कर सकता है। मैनुअल स्थानांतरण (जैसे ret2dlresolve) बनाते समय, आपको सही संस्करण अनुक्रमांक प्रदान करना होगा, अन्यथा समाधान विफल हो जाता है।
|
||||
|
||||
## गतिशील अनुभाग
|
||||
```
|
||||
readelf -d lnstat
|
||||
@ -229,11 +249,28 @@ Tag Type Name/Value
|
||||
0x000000006ffffff9 (RELACOUNT) 15
|
||||
0x0000000000000000 (NULL) 0x0
|
||||
```
|
||||
NEEDED निर्देशिका यह संकेत करती है कि प्रोग्राम को जारी रखने के लिए **उल्लेखित पुस्तकालय को लोड करने की आवश्यकता है**। NEEDED निर्देशिका तब पूरी होती है जब साझा **पुस्तकालय पूरी तरह से कार्यात्मक और उपयोग के लिए तैयार है**।
|
||||
The NEEDED directory यह संकेत करता है कि प्रोग्राम को जारी रखने के लिए **उल्लेखित लाइब्रेरी को लोड करने की आवश्यकता है**। NEEDED directory तब पूरी होती है जब साझा **लाइब्रेरी पूरी तरह से कार्यात्मक और उपयोग के लिए तैयार** होती है।
|
||||
|
||||
### डायनामिक लोडर खोज क्रम (RPATH/RUNPATH, $ORIGIN)
|
||||
|
||||
`DT_RPATH` (deprecated) और/या `DT_RUNPATH` यह प्रभावित करते हैं कि डायनामिक लोडर निर्भरताओं के लिए कहाँ खोजता है। मोटे तौर पर क्रम:
|
||||
|
||||
- `LD_LIBRARY_PATH` (setuid/sgid या अन्यथा "सुरक्षित-निष्पादन" प्रोग्रामों के लिए अनदेखा)
|
||||
- `DT_RPATH` (केवल यदि `DT_RUNPATH` अनुपस्थित है)
|
||||
- `DT_RUNPATH`
|
||||
- `ld.so.cache`
|
||||
- डिफ़ॉल्ट निर्देशिकाएँ जैसे `/lib64`, `/usr/lib64`, आदि।
|
||||
|
||||
`$ORIGIN` को RPATH/RUNPATH के अंदर मुख्य ऑब्जेक्ट के निर्देशिका का संदर्भ देने के लिए उपयोग किया जा सकता है। एक हमलावर के दृष्टिकोण से, यह तब महत्वपूर्ण होता है जब आप फ़ाइल सिस्टम लेआउट या वातावरण को नियंत्रित करते हैं। मजबूत बाइनरी (AT_SECURE) के लिए अधिकांश पर्यावरण चर लोडर द्वारा अनदेखा किए जाते हैं।
|
||||
|
||||
- निरीक्षण करें: `readelf -d ./bin | egrep -i 'r(path|unpath)'`
|
||||
- त्वरित परीक्षण: `LD_DEBUG=libs ./bin 2>&1 | grep -i find` (खोज पथ निर्णय दिखाता है)
|
||||
|
||||
> Priv-esc टिप: लिखने योग्य RUNPATHs या आपके द्वारा स्वामित्व वाले गलत कॉन्फ़िगर किए गए `$ORIGIN`-सापेक्ष पथों का दुरुपयोग करना पसंद करें। LD_PRELOAD/LD_AUDIT सुरक्षित-निष्पादन (setuid) संदर्भों में अनदेखा किए जाते हैं।
|
||||
|
||||
## पुनर्स्थापनाएँ
|
||||
|
||||
लोडर को लोड करने के बाद निर्भरताओं को भी पुनर्स्थापित करना चाहिए। इन पुनर्स्थापनों को REL या RELA प्रारूपों में पुनर्स्थापन तालिका में संकेतित किया गया है और पुनर्स्थापनों की संख्या गतिशील अनुभागों RELSZ या RELASZ में दी गई है।
|
||||
लोडर को निर्भरताओं को लोड करने के बाद पुनर्स्थापित भी करना चाहिए। ये पुनर्स्थापनाएँ REL या RELA प्रारूपों में पुनर्स्थापन तालिका में संकेतित होती हैं और पुनर्स्थापनों की संख्या डायनामिक अनुभागों RELSZ या RELASZ में दी जाती है।
|
||||
```
|
||||
readelf -r lnstat
|
||||
|
||||
@ -274,7 +311,6 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
00000001fea0 000900000402 R_AARCH64_JUMP_SL 0000000000000000 perror@GLIBC_2.17 + 0
|
||||
00000001fea8 000b00000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0
|
||||
00000001feb0 000c00000402 R_AARCH64_JUMP_SL 0000000000000000 putc@GLIBC_2.17 + 0
|
||||
00000001feb8 000d00000402 R_AARCH64_JUMP_SL 0000000000000000 opendir@GLIBC_2.17 + 0
|
||||
00000001fec0 000e00000402 R_AARCH64_JUMP_SL 0000000000000000 fputc@GLIBC_2.17 + 0
|
||||
00000001fec8 001100000402 R_AARCH64_JUMP_SL 0000000000000000 snprintf@GLIBC_2.17 + 0
|
||||
00000001fed0 001200000402 R_AARCH64_JUMP_SL 0000000000000000 __snprintf_chk@GLIBC_2.17 + 0
|
||||
@ -308,23 +344,41 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
```
|
||||
### स्थिर पुनर्स्थापनाएँ
|
||||
|
||||
यदि **कार्यक्रम एक अलग स्थान पर लोड होता है** जो पसंदीदा पते (आमतौर पर 0x400000) से भिन्न है क्योंकि पता पहले से उपयोग में है या **ASLR** या किसी अन्य कारण से, तो एक स्थिर पुनर्स्थापनाएँ **पॉइंटर्स को सही करती हैं** जिनके मानों ने बाइनरी के पसंदीदा पते पर लोड होने की अपेक्षा की थी।
|
||||
यदि **कार्यक्रम एक अलग स्थान पर लोड होता है** जो पसंदीदा पते (आमतौर पर 0x400000) से भिन्न है क्योंकि पता पहले से ही उपयोग में है या **ASLR** या किसी अन्य कारण से, तो एक स्थिर पुनर्स्थापन **पॉइंटर्स को सही करता है** जिनके मानों ने बाइनरी के पसंदीदा पते पर लोड होने की अपेक्षा की थी।
|
||||
|
||||
उदाहरण के लिए, `R_AARCH64_RELATIV` प्रकार के किसी भी अनुभाग को पुनर्स्थापन बायस के साथ पते को संशोधित करना चाहिए और जोड़ने वाले मान को जोड़ना चाहिए।
|
||||
उदाहरण के लिए, `R_AARCH64_RELATIV` प्रकार के किसी भी अनुभाग को पुनर्स्थापन पूर्वाग्रह के साथ पते को संशोधित करना चाहिए और जोड़ने वाले मान को जोड़ना चाहिए।
|
||||
|
||||
### गतिशील पुनर्स्थापनाएँ और GOT
|
||||
|
||||
पुनर्स्थापन एक बाहरी प्रतीक (जैसे किसी निर्भरता से एक फ़ंक्शन) को भी संदर्भित कर सकता है। जैसे कि libC से malloc फ़ंक्शन। फिर, लोडर जब libC को एक पते पर लोड करता है, तो यह जांचता है कि malloc फ़ंक्शन कहाँ लोड होता है, यह पता GOT (ग्लोबल ऑफ़सेट टेबल) तालिका में लिखता है (जो पुनर्स्थापन तालिका में निर्दिष्ट है) जहाँ malloc का पता निर्दिष्ट किया जाना चाहिए।
|
||||
पुनर्स्थापन एक बाहरी प्रतीक (जैसे किसी निर्भरता से एक फ़ंक्शन) को भी संदर्भित कर सकता है। जैसे कि libC से malloc फ़ंक्शन। फिर, लोडर जब libC को एक पते पर लोड करता है, तो यह जांचता है कि malloc फ़ंक्शन कहाँ लोड हुआ है, यह पता GOT (ग्लोबल ऑफसेट टेबल) तालिका में लिखता है (जो पुनर्स्थापन तालिका में इंगित किया गया है) जहाँ malloc का पता निर्दिष्ट किया जाना चाहिए।
|
||||
|
||||
### प्रक्रिया लिंक टेबल
|
||||
### प्रक्रिया लिंक तालिका
|
||||
|
||||
PLT अनुभाग आलसी बाइंडिंग करने की अनुमति देता है, जिसका अर्थ है कि किसी फ़ंक्शन के स्थान का समाधान पहली बार जब इसे एक्सेस किया जाता है, तब किया जाएगा।
|
||||
|
||||
तो जब एक कार्यक्रम malloc को कॉल करता है, तो यह वास्तव में PLT में `malloc` के संबंधित स्थान को कॉल करता है (`malloc@plt`)। जब इसे पहली बार कॉल किया जाता है, तो यह `malloc` का पता हल करता है और इसे संग्रहीत करता है ताकि अगली बार जब `malloc` को कॉल किया जाए, तो उस पते का उपयोग PLT कोड के बजाय किया जाए।
|
||||
तो जब एक कार्यक्रम malloc को कॉल करता है, तो यह वास्तव में PLT में `malloc` के संबंधित स्थान को कॉल करता है (`malloc@plt`)। पहली बार जब इसे कॉल किया जाता है, तो यह `malloc` का पता हल करता है और इसे संग्रहीत करता है ताकि अगली बार जब `malloc` को कॉल किया जाए, तो उस पते का उपयोग PLT कोड के बजाय किया जाए।
|
||||
|
||||
#### आधुनिक लिंकिंग व्यवहार जो शोषण को प्रभावित करते हैं
|
||||
|
||||
- `-z now` (पूर्ण RELRO) आलसी बाइंडिंग को निष्क्रिय करता है; PLT प्रविष्टियाँ अभी भी मौजूद हैं लेकिन GOT/PLT को केवल पढ़ने के लिए मैप किया गया है, इसलिए **GOT ओवरराइट** और **ret2dlresolve** जैसी तकनीकें मुख्य बाइनरी के खिलाफ काम नहीं करेंगी (पुस्तकालय अभी भी आंशिक रूप से RELRO हो सकते हैं)। देखें:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
- `-fno-plt` संकलक को **GOT प्रविष्टि सीधे** बाहरी फ़ंक्शनों को कॉल करने के लिए बनाता है बजाय PLT स्टब के माध्यम से जाने के। आप कॉल अनुक्रम देखेंगे जैसे `mov reg, [got]; call reg` बजाय `call func@plt` के। यह अनुमानित-कार्य निष्पादन के दुरुपयोग को कम करता है और PLT स्टब के चारों ओर ROP गैजेट शिकार को थोड़ा बदलता है।
|
||||
|
||||
- PIE बनाम स्थिर-PIE: PIE (ET_DYN के साथ `INTERP`) गतिशील लोडर की आवश्यकता होती है और सामान्य PLT/GOT मशीनरी का समर्थन करता है। स्थिर-PIE (ET_DYN बिना `INTERP`) में पुनर्स्थापनाएँ कर्नेल लोडर द्वारा लागू की जाती हैं और कोई `ld.so` नहीं होता; रनटाइम पर PLT समाधान की अपेक्षा न करें।
|
||||
|
||||
> यदि GOT/PLT एक विकल्प नहीं है, तो अन्य लिखने योग्य कोड-पॉइंटर्स पर स्विच करें या libc में क्लासिक ROP/SROP का उपयोग करें।
|
||||
|
||||
{{#ref}}
|
||||
../arbitrary-write-2-exec/aw2exec-got-plt.md
|
||||
{{#endref}}
|
||||
|
||||
## कार्यक्रम प्रारंभिककरण
|
||||
|
||||
कार्यक्रम के लोड होने के बाद इसे चलाने का समय होता है। हालाँकि, जो पहला कोड चलाया जाता है वह हमेशा `main` फ़ंक्शन नहीं होता है। इसका कारण यह है कि उदाहरण के लिए C++ में यदि एक **वैश्विक चर एक वर्ग का ऑब्जेक्ट है**, तो इस ऑब्जेक्ट को **main चलने से पहले** **प्रारंभिककरण** करना चाहिए, जैसे कि:
|
||||
कार्यक्रम के लोड होने के बाद इसे चलाने का समय होता है। हालाँकि, जो पहला कोड चलाया जाता है वह हमेशा `main` फ़ंक्शन नहीं होता है। इसका कारण यह है कि उदाहरण के लिए C++ में यदि एक **वैश्विक चर एक वर्ग का ऑब्जेक्ट है**, तो इस ऑब्जेक्ट को **main चलने से पहले** **आरंभ** किया जाना चाहिए, जैसे कि:
|
||||
```cpp
|
||||
#include <stdio.h>
|
||||
// g++ autoinit.cpp -o autoinit
|
||||
@ -345,38 +399,75 @@ printf("Main\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
ध्यान दें कि ये वैश्विक चर `.data` या `.bss` में स्थित हैं, लेकिन सूचियों `__CTOR_LIST__` और `__DTOR_LIST__` में प्रारंभ और नष्ट करने के लिए वस्तुएं संग्रहीत की जाती हैं ताकि उन्हें ट्रैक किया जा सके।
|
||||
ध्यान दें कि ये वैश्विक चर `.data` या `.bss` में स्थित हैं, लेकिन सूचियों `__CTOR_LIST__` और `__DTOR_LIST__` में प्रारंभ और विनाश के लिए वस्तुएं संग्रहीत की जाती हैं ताकि उन्हें ट्रैक किया जा सके।
|
||||
|
||||
C कोड से समान परिणाम प्राप्त करना संभव है GNU एक्सटेंशन का उपयोग करके:
|
||||
C कोड से GNU एक्सटेंशन का उपयोग करके समान परिणाम प्राप्त करना संभव है:
|
||||
```c
|
||||
__attributte__((constructor)) //Add a constructor to execute before
|
||||
__attributte__((destructor)) //Add to the destructor list
|
||||
```
|
||||
एक कंपाइलर के दृष्टिकोण से, `main` फ़ंक्शन के निष्पादन से पहले और बाद में इन क्रियाओं को निष्पादित करने के लिए, एक `init` फ़ंक्शन और एक `fini` फ़ंक्शन बनाना संभव है, जिन्हें गतिशील अनुभाग में **`INIT`** और **`FIN`** के रूप में संदर्भित किया जाएगा। और इन्हें ELF के `init` और `fini` अनुभागों में रखा गया है।
|
||||
From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF.
|
||||
|
||||
दूसरा विकल्प, जैसा कि उल्लेख किया गया है, **`INIT_ARRAY`** और **`FINI_ARRAY`** प्रविष्टियों में **`__CTOR_LIST__`** और **`__DTOR_LIST__`** सूचियों को संदर्भित करना है और इनकी लंबाई **`INIT_ARRAYSZ`** और **`FINI_ARRAYSZ`** द्वारा इंगित की जाती है। प्रत्येक प्रविष्टि एक फ़ंक्शन पॉइंटर है जिसे बिना तर्कों के कॉल किया जाएगा।
|
||||
The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments.
|
||||
|
||||
इसके अलावा, एक **`PREINIT_ARRAY`** भी हो सकता है जिसमें **pointers** होंगे जो **`INIT_ARRAY`** पॉइंटर्स से **पहले** निष्पादित किए जाएंगे।
|
||||
Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers.
|
||||
|
||||
#### Exploitation note
|
||||
|
||||
- Under Partial RELRO these arrays live in pages that are still writable before `ld.so` flips `PT_GNU_RELRO` to read-only. If you get an arbitrary write early enough or you can target a library’s writable arrays, you can hijack control flow by overwriting an entry with a function of your choice. Under Full RELRO they are read-only at runtime.
|
||||
|
||||
- For lazy binding abuse of the dynamic linker to resolve arbitrary symbols at runtime, see the dedicated page:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2dlresolve.md
|
||||
{{#endref}}
|
||||
|
||||
### Initialization Order
|
||||
|
||||
1. प्रोग्राम को मेमोरी में लोड किया जाता है, स्थिर वैश्विक चर **`.data`** में प्रारंभिक किया जाता है और अनियोजित वाले **`.bss`** में शून्य किए जाते हैं।
|
||||
1. प्रोग्राम मेमोरी में लोड होता है, स्थिर वैश्विक चर **`.data`** में प्रारंभिक होते हैं और अनियोजित शून्य होते हैं **`.bss`** में।
|
||||
2. प्रोग्राम या पुस्तकालयों के सभी **dependencies** **initialized** होते हैं और **dynamic linking** निष्पादित होता है।
|
||||
3. **`PREINIT_ARRAY`** फ़ंक्शन निष्पादित होते हैं।
|
||||
4. **`INIT_ARRAY`** फ़ंक्शन निष्पादित होते हैं।
|
||||
5. यदि एक **`INIT`** प्रविष्टि है, तो इसे कॉल किया जाता है।
|
||||
6. यदि एक पुस्तकालय है, तो dlopen यहाँ समाप्त होता है, यदि एक प्रोग्राम है, तो **real entry point** (`main` फ़ंक्शन) को कॉल करने का समय होता है।
|
||||
3. **`PREINIT_ARRAY`** कार्य निष्पादित होते हैं।
|
||||
4. **`INIT_ARRAY`** कार्य निष्पादित होते हैं।
|
||||
5. यदि कोई **`INIT`** प्रविष्टि है, तो इसे कॉल किया जाता है।
|
||||
6. यदि एक पुस्तकालय है, तो dlopen यहाँ समाप्त होता है, यदि एक प्रोग्राम है, तो **real entry point** (`main` function) को कॉल करने का समय है।
|
||||
|
||||
## Thread-Local Storage (TLS)
|
||||
|
||||
इन्हें C++ में कीवर्ड **`__thread_local`** या GNU एक्सटेंशन **`__thread`** का उपयोग करके परिभाषित किया गया है।
|
||||
They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**.
|
||||
|
||||
प्रत्येक थ्रेड इस चर के लिए एक अद्वितीय स्थान बनाएगा ताकि केवल थ्रेड अपने चर तक पहुँच सके।
|
||||
Each thread will maintain a unique location for this variable so only the thread can access its variable.
|
||||
|
||||
जब इसका उपयोग किया जाता है, तो ELF में अनुभाग **`.tdata`** और **`.tbss`** का उपयोग किया जाता है। जो `.data` (प्रारंभिक) और `.bss` (अनियोजित) के समान होते हैं लेकिन TLS के लिए।
|
||||
When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS.
|
||||
|
||||
प्रत्येक चर का TLS हेडर में एक प्रविष्टि होगी जो आकार और TLS ऑफसेट को निर्दिष्ट करती है, जो थ्रेड के स्थानीय डेटा क्षेत्र में उपयोग किया जाने वाला ऑफसेट है।
|
||||
Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area.
|
||||
|
||||
`__TLS_MODULE_BASE` एक प्रतीक है जिसका उपयोग थ्रेड स्थानीय भंडारण के आधार पते को संदर्भित करने के लिए किया जाता है और यह मेमोरी के उस क्षेत्र की ओर इशारा करता है जिसमें एक मॉड्यूल के सभी थ्रेड-स्थानीय डेटा होते हैं।
|
||||
The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
|
||||
|
||||
## Auxiliary Vector (auxv) and vDSO
|
||||
|
||||
The Linux kernel passes an auxiliary vector to processes containing useful addresses and flags for the runtime:
|
||||
|
||||
- `AT_RANDOM`: points to 16 random bytes used by glibc for the stack canary and other PRNG seeds.
|
||||
- `AT_SYSINFO_EHDR`: base address of the vDSO mapping (handy to find `__kernel_*` syscalls and gadgets).
|
||||
- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ`, आदि।
|
||||
|
||||
As an attacker, if you can read memory or files under `/proc`, you can often leak these without an infoleak in the target process:
|
||||
```bash
|
||||
# Show the auxv of a running process
|
||||
cat /proc/$(pidof target)/auxv | xxd
|
||||
|
||||
# From your own process (helper snippet)
|
||||
#include <sys/auxv.h>
|
||||
#include <stdio.h>
|
||||
int main(){
|
||||
printf("AT_RANDOM=%p\n", (void*)getauxval(AT_RANDOM));
|
||||
printf("AT_SYSINFO_EHDR=%p\n", (void*)getauxval(AT_SYSINFO_EHDR));
|
||||
}
|
||||
```
|
||||
`AT_RANDOM` का लीक करना आपको कैनरी मान देता है यदि आप उस पॉइंटर को डेरिफरेंस कर सकते हैं; `AT_SYSINFO_EHDR` आपको गैजेट्स के लिए खनन करने या सीधे तेज़ सिस्टम कॉल करने के लिए एक vDSO आधार देता है।
|
||||
|
||||
## References
|
||||
|
||||
- ld.so(8) – Dynamic Loader search order, RPATH/RUNPATH, secure-execution rules (AT_SECURE): https://man7.org/linux/man-pages/man8/ld.so.8.html
|
||||
- getauxval(3) – Auxiliary vector and AT_* constants: https://man7.org/linux/man-pages/man3/getauxval.3.html
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user