Translated ['binary-exploitation/heap/README.md'] to in

This commit is contained in:
Translator 2024-05-09 18:08:05 +00:00
parent fb0b65d946
commit 4eb3a11d2f
7 changed files with 154 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View file

@ -1 +1,155 @@
# हीप
## हीप की मूल बातें
हीप वह स्थान है जहाँ कोई प्रोग्राम डेटा स्टोर करने के लिए सक्षम होगा जब वह **`malloc`**, `calloc` जैसी फ़ंक्शन को कॉल करके डेटा का अनुरोध करेगा। इसके अतिरिक्त, जब यह मेमोरी और नहीं चाहिए होती है तो फ़ंक्शन **`free`** को कॉल करके उपलब्ध कर दी जाती है।
जैसा कि दिखाया गया है, यह बस उसके बाद है जहाँ बाइनरी मेमोरी में लोड हो रहा है (चेक करें `[हीप]` खंड):
<figure><img src="../../.gitbook/assets/image (1241).png" alt=""><figcaption></figcaption></figure>
### मूल चंक आवंटन
जब किसी डेटा को हीप में स्टोर करने के लिए अनुरोध किया जाता है, तो उसके लिए हीप का कुछ स्थान आवंटित किया जाता है। यह स्थान एक बिन का होगा और केवल अनुरोधित डेटा + बिन हेडर के स्थान + न्यूनतम बिन आकार ऑफसेट चंक के लिए आरक्षित किया जाएगा। लक्ष्य यह है कि हर चंक को ढूंढना जटिल न करते हुए संभावना हो कि जितनी कम संभावना हो सके मेमोरी को आरक्षित किया जाए। इसके लिए, मेटाडेटा चंक जानकारी का उपयोग किया जाता है ताकि पता चले कि हर उपयोग किया गया/फ्री चंक कहाँ है।
अनुरोधित मेमोरी को आरक्षित करने के लिए मुख्य रूप से विभिन्न तरीके हैं जो मुख्य रूप से उपयोग किए जाने वाले बिन पर निर्भर करते हैं, लेकिन एक सामान्य मेथडोलॉजी निम्नलिखित है:
* प्रोग्राम निश्चित मात्रा मेमोरी का अनुरोध करके शुरू होता है।
* यदि चंक की सूची में उपलब्ध कोई व्यक्ति अनुरोध को पूरा करने के लिए पर्याप्त बड़ा है, तो उसका उपयोग किया जाएगा
* यह यह भी मतलब हो सकता है कि उपलब्ध चंक का हिस्सा इस अनुरोध के लिए उपयोग किया जाएगा और शेष चंक सूची में जोड़ दिया जाएगा
* यदि सूची में कोई उपलब्ध चंक नहीं है लेकिन आवंटित हीप मेमोरी में अभी भी स्थान है, तो हीप प्रबंधक एक नया चंक बनाता है
* यदि नए चंक को आवंटित करने के लिए पर्याप्त हीप स्थान नहीं है, तो हीप प्रबंधक कर्नल से मांग करता है कि हीप के लिए आवंटित मेमोरी को विस्तारित किया जाए और फिर इस मेमोरी का उपयोग करके नए चंक उत्पन्न किए जाएं
* यदि सब कुछ असफल हो जाता है, `malloc` नल लौटाता है।
ध्यान दें कि यदि अनुरोधित **मेमोरी एक थ्रेशोल्ड पार करती है**, तो **`mmap`** का उपयोग किया जाएगा ताकि अनुरोधित मेमोरी को मैप किया जा सके।
### एरीना
**मल्टीथ्रेड** एप्लिकेशन में, हीप प्रबंधक को दुर्घटनाग्रस्त या इच्छित व्यय के खिलाफ सुरक्षित रखने के लिए **रेस कंडीशन** से बचना चाहिए। पहले, इसे केवल एक **ग्लोबल म्यूटेक्स** का उपयोग करके केवल एक थ्रेड हीप तक पहुंच सकता था, लेकिन यह **प्रदर्शन समस्याएं** उत्पन्न करता था क्योंकि म्यूटेक्स द्वारा उत्पन्न बॉटलनेक के कारण।
इस समस्या का समाधान करने के लिए, ptmalloc2 हीप आवंटकर्ता ने "एरीना" का परिचय किया, जहाँ **प्रत्येक एरीना** एक **अलग हीप** के रूप में काम करता है जिसमें उसके **अपने** डेटा **संरचनाएँ** और **म्यूटेक्स** होते हैं, जो अन्य एरीनों का उपयोग करने वाले अनेक थ्रेड्स को एक दूसरे के साथ हीप कार्यों करने की अनुमति देते हैं, जब तक वे अलग एरीनों का उपयोग करें।
डिफ़ॉल्ट "मुख्य" एरीना एकल-थ्रेड एप्लिकेशनों के लिए हीप कार्यों का संभालन करती है। जब **नए थ्रेड्स** जोड़े जाते हैं, हीप प्रबंधक उन्हें **सेकेंडरी एरीनों** को सौंपता है ताकि प्रतिस्पर्धा को कम किया जा सके। यह पहले प्रत्येक नए थ्रेड को एक अप्रयुक्त एरीना से जोड़ने का प्रयास करता है, जरूरत पड़ने पर नए एरीनों को बनाता है, 32-बिट सिस्टम के लिए CPU कोर्स की दोगुनी सीमा और 64-बिट सिस्टम के लिए 8 गुना की सीमा तक। एक बार सीमा पर पहुंच जाते हैं, **थ्रेड्स को एरीनों का साझा करना** पड़ता है, प्रतिस्पर्धा की संभावना होती है।
मुख्य एरीना की तरह, जो `brk` सिस्टम कॉल का उपयोग करके विस्तारित होता है, सेकेंडरी एरीनों `mmap` और `mprotect` का उपयोग करके "सबहीप्स" बनाते हैं ताकि हीप के व्यवहार को अनुकरण कर सकें, मल्टीथ्रेड कार्यों के लिए मेमोरी का प्रबंधन करने की लाचारता देते हैं।
### सबहीप्स
सबहीप्स मल्टीथ्रेड एप्लिकेशनों में सेकेंडरी एरीनों के लिए मेमोरी आरक्षित करते हैं, जिससे उन्हें मुख्य हीप से अलग रूप से अपने हीप क्षेत्रों को बढ़ाने और प्रबंधित करने की अनुमति मिले। यहाँ सबहीप्स मूल हीप से कैसे भिन्न हैं और वे कैसे काम करते हैं:
1. **मूल हीप vs. सबहीप्स**:
* मूल हीप सीधे प्रोग्राम के बाइनरी के बाद स्थित है, और यह `sbrk` सिस्टम कॉल का उपयोग करके विस्तारित होता है।
* सेकेंडरी एरीनों द्वारा उपयोग किए जाने वाले सबहीप्स, `mmap` के माध्यम से बनाए जाते हैं, एक सिस्टम कॉल जो एक निर्दिष्ट मेमोरी क्षेत्र को मैप करता है।
2. **`mmap` के साथ मेमोरी आरक्षण**:
* जब हीप प्रबंधक एक सबहीप बनाता है, तो वह `mmap` के माध्यम से एक बड़े ब्लॉक मेमोरी को आरक्षित करता है। यह आरक्षण मेमोरी को तुरंत आवंटित नहीं करता; यह बस एक क्षेत्र निर्धारित करता है जिसे अन्य सिस्टम प्रक्रियाएँ या आवंटन का उपयोग नहीं कर सकती हैं।
* डिफ़ॉल्ट रूप से, सबहीप्स के लिए आरक्षित आकार 32-बिट प्रक्रियाओं के लिए 1 MB है और 64-बिट प्रक्रियाओं के लिए 64 MB है।
3. **`mprotect` के साथ धीरे-धीरे विस्तार**:
* पहले से ही आरक्षित मेमोरी क्षेत्र को `PROT_NONE` के रूप में चिह्नित किया जाता ह
## बिन्स
चंक्स को स्टोर करने की क्षमता को बेहतर बनाने के लिए हर चंक्स केवल एक लिंक्ड लिस्ट में नहीं है, बल्कि कई प्रकार के होते हैं। ये हैं बिन्स और ये 5 प्रकार के बिन्स हैं: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) small bins, 63 large bins, 1 unsorted bin, 10 fast bins और 64 tcache bins प्रति थ्रेड।
अनसॉर्टेड, small और large बिन्स के प्रत्येक के लिए प्रारंभिक पता एक ही एरे में है। इंडेक्स 0 अप्रयुक्त है, 1 अनसॉर्टेड बिन है, बिन्स 2-64 small बिन्स हैं और बिन्स 65-127 large बिन्स हैं।
### Small Bins
Small bins large bins से तेज होते हैं लेकिन fast bins से धीमे होते हैं।
62 के प्रत्येक बिन में **एक ही आकार के चंक्स** होंगे: 16, 24, ... (32 बिट्स में 504 बाइट तक और 64 बिट्स में 1024 बाइट तक की अधिकतम आकार)। यह इसमें मदद करता है कि एक स्थान को कैसे आवंटित किया जाना चाहिए और इन सूचियों पर प्रविष्टि और हटाने की गति में मदद करता है।
### Large Bins
Small bins के विपरीत, जो निश्चित आकारों के चंक्स का प्रबंधन करते हैं, प्रत्येक **large bin एक चंक साइज की श्रेणी का प्रबंधन** करता है। यह अधिक लचीला है, विभिन्न आकारों को समायोजित करने के लिए एक अलग बिन की आवश्यकता नहीं है।
एक मेमोरी आवंटक, large bins small bins समाप्त होने पर शुरू होते हैं। Large bins के लिए श्रेणियाँ प्रगतिशील रूप से बड़ी होती हैं, जिसका मतलब है कि पहला बिन 512 से 576 बाइट तक के चंक्स को कवर कर सकता है, जबकि अगला 576 से 640 बाइट को कवर करता है। यह पैटर्न जारी रहता है, सबसे बड़े बिन में सभी 1MB से ऊपर के चंक्स को कवर करता है।
Large bins small bins की तुलना में धीमे होते हैं क्योंकि उन्हें **एक सूची में भिन्न चंक साइज की खोज और क्रमबद्ध करना** होता है एक आवंटन के लिए सबसे अच्छा मेल ढूंढने के लिए। जब एक चंक large bin में डाला जाता है, तो इसे क्रमबद्ध किया जाना चाहिए, और जब मेमोरी आवंटित की जाती है, तो सिस्टम को सही चंक ढूंढना होता है। यह अतिरिक्त काम उन्हें **धीमा** बनाता है, लेकिन क्योंकि बड़ी आवंटन छोटे से कम होते हैं, यह एक स्वीकार्य व्यापार है।
यहाँ हैं:
* 32 बिन्स की 64B रेंज
* 16 बिन्स की 512B रेंज
* 8 बिन्स की 4096B रेंज
* 4 बिन्स की 32768B रेंज
* 2 बिन्स की 262144B रेंज
* 1 बिन्स बची हुई आकारों के लिए
### अनसॉर्टेड बिन
अनसॉर्टेड बिन एक **तेज कैश** है जिसका हीप प्रबंधक द्वारा मेमोरी आवंटन को तेज करने के लिए उपयोग किया जाता है। यहाँ यह कैसे काम करता है: जब कोई प्रोग्राम मेमोरी को मुक्त करता है, तो हीप प्रबंधक उसे तुरंत किसी विशिष्ट बिन में नहीं डालता है। बल्कि, यह पहले किसी भी पड़ोसी फ्री चंक्स के साथ **मर्ज करने की कोशिश करता है** ताकि एक बड़े फ्री मेमोरी ब्लॉक बना सके। फिर, यह नया चंक इस नए चंक को "अनसॉर्टेड बिन" कहलाने वाले सामान्य बिन में रखता है।
जब कोई प्रोग्राम **मेमोरी के लिए अनुरोध करता है**, तो हीप प्रबंधक **पहले अनसॉर्टेड बिन की जाँच करता है** कि क्या वहाँ सही साइज का चंक है। अगर वह एक पाता है, तो वह तुरंत उसे उपयोग करता है, जो अन्य बिन्स में खोजने से तेज है। अगर उसे उपयुक्त चंक नहीं मिलता है, तो वह मुक्त चंक्स को उनके सही बिन्स में ले जाता है, या तो छोटे या बड़े, उनके आकार के आधार पर।
इसलिए, अनसॉर्टेड बिन एक तरीका है मेमोरी आवंटन को तेज करने के लिए हाल ही में मुक्त मेमोरी को तेजी से पुनः उपयोग करके और समय ग्राहक खोज और मर्ज की आवश्यकता को कम करके।
{% hint style="danger" %}
ध्यान दें कि चंक्स विभिन्न श्रेणियों के होने के बावजूद, समय-समय पर, यदि एक उपलब्ध चंक किसी अन्य उपलब्ध चंक के साथ टकरा रहा है (यदि वे विभिन्न श्रेणियों के हों), तो वे मर्ज किए जाएंगे।
{% endhint %}
### फास्ट बिन्स
फास्ट बिन्स छोटे चंक्स के लिए मेमोरी आवंटन को **तेज करने के लिए डिज़ाइन किए गए हैं** जिसे हाल ही में मुक्त चंक्स को एक त्वरित पहुंच संरचना में रखकर किया जाता है। ये बिन्स एक लास्ट-इन, फर्स्ट-आउट (LIFO) दृष्टिकोण का उपयोग करते हैं, जिसका मतलब है कि **सबसे हाल ही मुक्त चंक पहला** है जो एक नए आवंटन अनुरोध होने पर पुनः उपयोग किया जाता है। यह व्यवहार गति के लिए फायदेमंद है, क्योंकि एक स्टैक (LIFO) के शीर्ष से डालना और हटाना एक कतार (FIFO) की तुलना में तेज होता है।
इसके अतिरिक्त, **फास्ट बिन्स एकल लिंक्ड लिस्ट का उपयोग करते हैं**, डबल लिंक्ड नहीं, जो गति को और बढ़ाता है। क्योंकि फास्ट बिन्स में चंक्स को पड़ोसियों के साथ मर्ज नहीं किया जाता है, इसके लिए एक जटिल संरचना की आवश्यकता नहीं है जो मध्य से हटाने की अनुमति देती है। एकल लिंक्ड लिस्ट इन संचालनों के लिए सरल और तेज है।
मूल रूप से, यहाँ यह होता है कि हेडर (पहले चंक के पॉइंटर) हमेशा उस आकार के नवीनतम मुक्त चंक की ओर पोइंट कर रहा है। तो:
* जब उस आकार का नया चंक आवंटित किया जाता है, तो हेडर एक उपयुक्त मुक्त चंक की ओर पोइंट कर रहा है। क्योंकि यह मुक्त चंक अगले उपयोग के लिए पोइंट कर रहा है, इस पते को हेडर में स्टोर किया जाता है ताकि अगली आवंटन जाने के लिए कहाँ से एक उपलब्ध चंक मिलेगा
* जब एक चंक मुक्त किया जाता है, तो मुक्त चंक वर्तमान उपलब्ध चंक के पते को सहेजेगा और इस नए मुक्त चंक का पता ह
### बिन्स क्रम
#### आवंटन के लिए:
1. अगर उस आकार के Tcache में उपलब्ध चंक है, तो Tcache का उपयोग करें
2. अगर यह बहुत बड़ा है, तो mmap का उपयोग करें
3. एरीना हीप लॉक प्राप्त करें और:
1. अगर प्रार्थित आकार के लिए उपलब्ध छोटे आकार का फास्ट बिन चंक है, तो उसका उपयोग करें और तत्काल बिन से tcache को पूर्वावलंबित करें
2. एक चंक मिलने की संभावना है, तो असंक्षेप्त सूची में प्रत्येक प्रविष्टि की जांच करें जिसमें एक बड़ा पर्याप्त चंक है, और यदि संभव हो तो tcache को पूर्वावलंबित करें
3. छोटे बिन्स या बड़े बिन्स (अनुरोधित आकार के अनुसार) की जांच करें और यदि संभव हो तो tcache को पूर्वावलंबित करें
4. उपलब्ध स्मृति से नया चंक बनाएं
1. अगर उपलब्ध स्मृति नहीं है, तो `sbrk` का उपयोग करके अधिक प्राप्त करें
2. यदि मुख्य हीप स्मृति अधिक नहीं बढ़ सकती है, तो mmap का उपयोग करके एक नया स्थान बनाएं
5. अगर कुछ काम नहीं किया, तो null लौटें
**मुक्त करने के लिए:**
1. यदि पॉइंटर नल है, तो समाप्त करें
2. चंक में `free` सांत्वना जांचें करें ताकि यह एक वैध चंक है यह सत्यापित करने की कोशिश करें
1. यदि पर्याप्त छोटा है और tcache भरा नहीं है, तो उसे वहाँ डालें
2. यदि बिट M सेट है (हीप नहीं), तो `munmap` का उपयोग करें
3. एरीना हीप लॉक प्राप्त करें:
1. अगर यह एक फास्टबिन में फिट होता है, तो उसे वहाँ डालें
2. यदि चंक > 64KB है, तो तत्काल फास्टबिन को समेटें और परिणामस्वरूप मिले चंक को असंक्षेप्त बिन पर डालें।
3. चंक को पिछले और आगे की ओर मिलाएं छोटे, बड़े और असंक्षेप्त बिन्स में यदि कोई है।
4. यदि सिर के शीर्ष में है, तो इसे अप्रयुक्त स्मृति में मिलाएं
5. यदि पिछले वाले नहीं हैं, तो इसे असंक्षेप्त सूची में संग्रहित करें
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(void)
{
char *ptr;
ptr = malloc(0x10);
strcpy(ptr, "panda");
}
```
मुख्य कार्यक्रम के अंत में एक ब्रेकपॉइंट सेट करें और चलो देखते हैं कि जानकारी कहाँ संग्रहित की गई थी:
<figure><img src="../../.gitbook/assets/image (1239).png" alt=""><figcaption></figcaption></figure>
यह देखना संभव है कि स्ट्रिंग पांडा को `0xaaaaaaac12a0` पर संग्रहित किया गया था (जो `x0` के अंदर malloc द्वारा प्रतिक्रिया के रूप में दिया गया पता था)। इससे पहले 0x10 बाइट जांचने पर देखा जा सकता है कि `0x0` यह दिखाता है कि **पिछला चंक उपयोग नहीं हुआ** (लंबाई 0) और इस चंक की लंबाई `0x21` है।
अतिरिक्त रिजर्व किए गए रिक्त स्थान (0x21-0x10=0x11) **जोड़े गए हेडर** (0x10) से आते हैं और 0x1 यह नहीं दिखाता है कि 0x21B रिजर्व किया गया था, बल्कि वर्तमान हेडर की लंबाई के आखिरी 3 बिटों में कुछ विशेष अर्थ हैं। क्योंकि लंबाई हमेशा 16-बाइट एलाइन की जाती है (64-बिट मशीनों में), इन बिट्स का उपयोग वास्तव में कभी भी लंबाई संख्या द्वारा नहीं किया जाएगा।
```
0x1: Previous in Use - Specifies that the chunk before it in memory is in use
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena
```
##
## संदर्भ
* [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
* [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)