<summary><strong>Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Ειδικός Red Team του HackTricks AWS)</strong></a><strong>!</strong></summary>
*Αν θέλετε να δείτε την **εταιρεία σας διαφημισμένη στο HackTricks** ή να**κατεβάσετε το HackTricks σε μορφή PDF** ελέγξτε τα [**ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ**](https://github.com/sponsors/carlospolop)!
* Αποκτήστε το [**επίσημο PEASS & HackTricks swag**](https://peass.creator-spring.com)
* Ανακαλύψτε την [**Οικογένεια PEASS**](https://opensea.io/collection/the-peass-family), τη συλλογή μας από αποκλειστικά [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Εγγραφείτε στη** 💬 [**ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στη [**ομάδα τηλεγραφήματος**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Μοιραστείτε τα χάκινγκ κόλπα σας υποβάλλοντας PRs στα** [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) αποθετήρια του github.
Για να βελτιωθεί η αποδοτικότητα στον τρόπο αποθήκευσης των κομματιών, κάθε κομμάτι δεν βρίσκεται μόνο σε μία συνδεδεμένη λίστα, αλλά υπάρχουν διάφοροι τύποι. Αυτοί είναι οι bins και υπάρχουν 5 τύποι bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) μικροί bins, 63 μεγάλοι bins, 1 unsorted bin, 10 fast bins και 64 tcache bins ανά thread.
Η αρχική διεύθυνση για κάθε unsorted, μικρό και μεγάλο bin βρίσκεται μέσα στον ίδιο πίνακα. Το δείκτης 0 δεν χρησιμοποιείται, το 1 είναι το unsorted bin, τα bins 2-64 είναι μικροί bins και τα bins 65-127 είναι μεγάλοι bins.
Ακόμα κι αν τα threads προσπαθούν να έχουν τη δική τους στοίβα (δείτε [Αρένες](bins-and-memory-allocations.md#arenas) και [Υποστοίβες](bins-and-memory-allocations.md#subheaps)), υπάρχει η πιθανότητα ότι ένας διεργασία με πολλά threads (όπως ένας web server) **θα μοιραστεί τη στοίβα με άλλα threads**. Σε αυτήν την περίπτωση, η κύρια λύση είναι η χρήση **κλειδαριών**, οι οποίες μπορεί **να επιβραδύνουν σημαντικά τα threads**.
Επομένως, ένα tcache είναι παρόμοιο με ένα fast bin ανά thread στον τρόπο που είναι μια **μονόδρομη συνδεδεμένη λίστα** που δεν ενώνει κομμάτια. Κάθε thread έχει **64 μονόδρομους tcache bins**. Κάθε bin μπορεί να έχει ένα μέγιστο των [7 κομματιών ίδιου μεγέθους](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) κυμαίνονται από [24 έως 1032B σε 64-bit συστήματα και 12 έως 516B σε 32-bit συστήματα](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
**Όταν ένα thread απελευθερώνει** ένα κομμάτι, **αν δεν είναι πολύ μεγάλο**γιανα εκχωρηθεί στο tcache και το αντίστοιχο tcache bin **δεν είναι γεμάτο** (ήδη 7 κομμάτια), **θα εκχωρηθεί εκεί**. Αν δεν μπορεί να πάει στο tcache, θα πρέπει να περιμένει το κλείδωμα της στοίβας γιανα μπορέσει να εκτελέσει την πράξη απελευθέρωσης παγκοσμίως.
Όταν ένα **κομμάτι εκχωρείται**, αν υπάρχει ένα ελεύθερο κομμάτι του απαιτούμενου μεγέθους στο **Tcache θα το χρησιμοποιήσει**, αν όχι, θα πρέπει να περιμένει το κλείδωμα της στοίβας γιανα βρει ένα στα γενικά bins ή να δημιουργήσει ένα νέο.\
Υπάρχει επίσης μια βελτιστοποίηση, σε αυτήν την περίπτωση, ενώ έχοντας το κλείδωμα της στοίβας, το thread **θα γεμίσει το Tcache του με κομμάτια στοίβας (7) του απαιτούμενου μεγέθους**, έτσι αν χρειαστεί περισσότερα, θα τα βρει στο Tcache.
<summary>Προσθέστε ένα παράδειγμα του tcache chunk</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
free(chunk);
return 0;
}
```
Εκτελέστε το και αποσφαλματώστε το με ένα σημείο αναμονής στον κώδικα επιστροφής (ret opcode) από την κύρια συνάρτηση (main function). Στη συνέχεια, με το gef μπορείτε να δείτε το tcache bin που χρησιμοποιείται:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
Στον παρακάτω κώδικα είναι δυνατόν να δούμε τα **max bins** και **chunks per index**, τη δομή **`tcache_entry`** που δημιουργήθηκε γιανα αποφευχθούν τα διπλά frees και τη **`tcache_perthread_struct`**, μια δομή που κάθε νήμα χρησιμοποιεί γιανα αποθηκεύσει τις διευθύνσεις σε κάθε δείκτη του bin.
<details>
<summary><code>tcache_entry</code> και <code>tcache_perthread_struct</code></summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c
/* We want 64 entries. This is an arbitrary limit, which tunables can reduce. */
Οι γρήγοροι κάδοι σχεδιάστηκαν γιανα**επιταχύνουν την εκχώρηση μνήμης για μικρά κομμάτια** κρατώντας πρόσφατα ελευθερωμένα κομμάτια σε μια δομή γρήγορης πρόσβασης. Αυτοί οι κάδοι χρησιμοποιούν μια προσέγγιση Τελευταίο Μέσα, Πρώτο Έξω (LIFO), που σημαίνει ότι το **πιο πρόσφατα ελευθερωμένο κομμάτι είναι το πρώτο** που θα χρησιμοποιηθεί όταν υπάρχει μια νέα αίτηση εκχώρησης. Αυτή η συμπεριφορά είναι επωφελής για την ταχύτητα, καθώς είναι πιο γρήγορο να εισαχθεί και να αφαιρεθεί από την κορυφή ενός σωρού (LIFO) σε σύγκριση με μια ουρά (FIFO).
Επιπλέον, **οι γρήγοροι κάδοι χρησιμοποιούν μονόδεσμες λίστες**, όχι διπλά δεσμευμένες, οι οποίες βελτιώνουν περαιτέρω την ταχύτητα. Δεδομένου ότι τα κομμάτια στους γρήγορους κάδους δεν συγχωνεύονται με γείτονες, δεν υπάρχει ανάγκη για μια πολύπλοκη δομή που επιτρέπει την αφαίρεση από τη μέση. Μια μονόδεσμη λίστα είναι απλούστερη και ταχύτερη για αυτές τις λειτουργίες.
Βασικά, αυτό που συμβαίνει εδώ είναι ότι η κεφαλίδα (ο δείκτης προς το πρώτο κομμάτι προς έλεγχο) δείχνει πάντα στο πιο πρόσφατα ελευθερωμένο κομμάτι αυτού του μεγέθους. Έτσι:
* Όταν εκχωρείται ένα νέο κομμάτι αυτού του μεγέθους, η κεφαλίδα δείχνει ένα ελεύθερο κομμάτι για χρήση. Δεδομένου ότι αυτό το ελεύθερο κομμάτι δείχνει στο επόμενο που θα χρησιμοποιηθεί, αυτή η διεύθυνση αποθηκεύεται στην κεφαλίδα ώστε η επόμενη εκχώρηση να ξέρει πού να πάρει ένα διαθέσιμο κομμάτι
* Όταν ένα κομμάτι ελευθερώνεται, το ελεύθερο κομμάτι θα αποθηκεύσει τη διεύθυνση του τρέχοντος διαθέσιμου κομματιού και η διεύθυνση αυτού του νεοελευθερωμένου κομματιού θα τεθεί στην κεφαλίδα
Το μέγιστο μέγεθος μιας συνδεδεμένης λίστας είναι `0x80` και οργανώνονται έτσι ώστε ένα κομμάτι μεγέθους `0x20-0x2f` θα βρίσκεται στο δείκτη `0`, ένα κομμάτι μεγέθους `0x30-0x3f` θα βρισκόταν στο δείκτη `1`...
Τα κομμάτια στους γρήγορους κάδους δεν ορίζονται ως διαθέσιμα, έτσι διατηρούνται ως κομμάτια γρήγορων κάδων για κάποιο χρονικό διάστημα αντί να είναι σε θέση να συγχωνευτούν με άλλα ελεύθερα κομμάτια που τα περιβάλλουν.
<summary>Προσθέστε ένα παράδειγμα γρήγορου κομματιού (fastbin chunk)</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[8];
int i;
// Loop to allocate memory 8 times
for (i = 0; i <8;i++){
chunks[i] = malloc(24);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i <8;i++){
free(chunks[i]);
}
return 0;
}
```
Σημειώστε πως εκχωρούμε και απελευθερώνουμε 8 τμήματα με τον ίδιο μέγεθος έτσι ώστε να γεμίσει το tcache και το όγδοο να αποθηκευτεί στο γρήγορο τμήμα.
Μεταγλωττίστε το και εντοπίστε το με ένα σημείο αναμονής στον κώδικα επιστροφής (ret opcode) από την κύρια συνάρτηση. Στη συνέχεια, με το gef μπορείτε να δείτε το γέμισμα του tcache bin και το ένα τμήμα στο γρήγορο bin:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
───────────────────────────────────────────────────────────────────────── Fastbins for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────────
Ο μη ταξινομημένος κάδος είναι ένας **προσωρινός αποθηκευτικός χώρος** που χρησιμοποιείται από τον διαχειριστή σωρού γιανα κάνει την εκχώρηση μνήμης πιο γρήγορη. Έτσι λειτουργεί: Όταν ένα πρόγραμμα απελευθερώνει ένα κομμάτι μνήμης και αν αυτό το κομμάτι δεν μπορεί να εκχωρηθεί σε έναν tcache ή γρήγορο κάδο και δεν συγκρούεται με το κομμάτι κορυφής, ο διαχειριστής σωρού δεν το τοποθετεί αμέσως σε ένα συγκεκριμένο μικρό ή μεγάλο κάδο. Αντίθετα, πρώτα προσπαθεί να**συγχωνεύσει το με κοντινά ελεύθερα κομμάτια**γιανα δημιουργήσει ένα μεγαλύτερο τμήμα ελεύθερης μνήμης. Στη συνέχεια, τοποθετεί αυτό το νέο κομμάτι σε ένα γενικό κάδο που ονομάζεται "μη ταξινομημένος κάδος".
Όταν ένα πρόγραμμα **ζητά μνήμη**, ο διαχειριστής σωρού **ελέγχει τον μη ταξινομημένο κάδο**γιανα δει αν υπάρχει ένα κομμάτι αρκετά μεγάλο. Αν βρει ένα, το χρησιμοποιεί αμέσως. Αν δε βρει ένα κατάλληλο κομμάτι στον μη ταξινομημένο κάδο, μεταφέρει όλα τα κομμάτια σε αυτή τη λίστα στους αντίστοιχους κάδους τους, είτε μικρούς είτε μεγάλους, με βάση το μέγεθός τους.
Σημειώστε ότι αν ένα μεγαλύτερο κομμάτι χωριστεί σε 2 μισά και το υπόλοιπο είναι μεγαλύτερο από το MINSIZE, θα τοποθετηθεί πίσω στον μη ταξινομημένο κάδο.
Έτσι, ο μη ταξινομημένος κάδος είναι ένας τρόπος γιανα επιταχύνει την εκχώρηση μνήμης με τον γρήγορο επαναχρησιμοποίηση πρόσφατα απελευθερωμένης μνήμης και τη μείωση της ανάγκης για χρονοβόρες αναζητήσεις και συγχωνεύσεις.
{% hint style="danger" %}
Σημειώστε ότι ακόμα κι αν τα κομμάτια ανήκουν σε διαφορετικές κατηγορίες, αν ένα διαθέσιμο κομμάτι συγκρούεται με ένα άλλο διαθέσιμο κομμάτι (ακόμα κι αν αρχικά ανήκουν σε διαφορετικούς κάδους), θα συγχωνευτούν.
<summary>Προσθέστε ένα παράδειγμα μη ταξινομημένου κομματιού</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[9];
int i;
// Loop to allocate memory 8 times
for (i = 0; i <9;i++){
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i <8;i++){
free(chunks[i]);
}
return 0;
}
```
Σημειώστε πως εκχωρούμε και απελευθερώνουμε 9 τμήματα με τον ίδιο μέγεθος έτσι ώστε **να γεμίσει το tcache** και το όγδοο να αποθηκευτεί στο unsorted bin επειδή είναι **πολύ μεγάλο για το fastbin** και το ένατο δεν απελευθερώνεται έτσι ώστε το ένατο και το όγδοο **να μη συγχωνευτούν με το top chunk**.
Μεταγλωττίστε το και αποσφαλματώστε το με ένα σημείο αναμονής στον κωδικό επιστροφής από τη συνάρτηση main. Στη συνέχεια, με το gef μπορείτε να δείτε το γέμισμα του tcache bin και το ένα τμήμα στο unsorted bin:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
───────────────────────────────────────────────────────────────────────── Fastbins for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────────
Fastbins[idx=0, size=0x20] 0x00
Fastbins[idx=1, size=0x30] 0x00
Fastbins[idx=2, size=0x40] 0x00
Fastbins[idx=3, size=0x50] 0x00
Fastbins[idx=4, size=0x60] 0x00
Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
Τα μικρά bins είναι ταχύτερα από τα μεγάλα bins αλλά πιο αργά από τα γρήγορα bins.
Κάθε bin από τα 62 θα έχει **κομμάτια με τον ίδιο μέγεθος**: 16, 24, ... (με μέγιστο μέγεθος 504 bytes σε 32bits και 1024 σε 64bits). Αυτό βοηθάει στην ταχύτητα εντοπισμού του bin όπου θα πρέπει να γίνει εκχώρηση χώρου και στην εισαγωγή και αφαίρεση καταχωρήσεων σε αυτές τις λίστες.
Έτσι υπολογίζεται το μέγεθος του μικρού bin ανάλογα με το δείκτη του bin:
<summary>Προσθέστε ένα παράδειγμα μικρού κομματιού</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[10];
int i;
// Loop to allocate memory 8 times
for (i = 0; i <9;i++){
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i <8;i++){
free(chunks[i]);
}
chunks[9] = malloc(0x110);
return 0;
}
```
Σημειώστε πως εκχωρούμε και απελευθερώνουμε 9 τμήματα του ίδιου μεγέθους έτσι ώστε **να γεμίσουν το tcache** και το όγδοο να αποθηκευτεί στον unsorted κάδο επειδή είναι **πολύ μεγάλο για το fastbin** και το ένατο δεν είναι ελεύθερο οπότε το ένατο και το όγδοο **δεν συγχωνεύονται με το top chunk**. Στη συνέχεια εκχωρούμε ένα μεγαλύτερο τμήμα μεγέθους 0x110 το οποίο κάνει **το τμήμα στον unsorted κάδο να πάει στον small κάδο**.
Μεταγλωττίστε το και αποσφαλματώστε το με ένα σημείο διακοπής στον κώδικα επιστροφής (ret opcode) από τη main συνάρτηση. Στη συνέχεια, με το gef μπορείτε να δείτε το γέμισμα του tcache bin και το ένα τμήμα στον small bin:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
───────────────────────────────────────────────────────────────────────── Fastbins for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────────
Fastbins[idx=0, size=0x20] 0x00
Fastbins[idx=1, size=0x30] 0x00
Fastbins[idx=2, size=0x40] 0x00
Fastbins[idx=3, size=0x50] 0x00
Fastbins[idx=4, size=0x60] 0x00
Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
Αντίθετα με τους μικρούς κάδους, οι οποίοι διαχειρίζονται κομμάτια με σταθερούς μεγέθη, **κάθε μεγάλος κάδος χειρίζεται ένα εύρος μεγεθών κομματιών**. Αυτό είναι πιο ευέλικτο, επιτρέποντας στο σύστημα να προσαρμόζεται σε **διάφορα μεγέθη** χωρίς την ανάγκη για έναν ξεχωριστό κάδο για κάθε μέγεθος.
Σε έναν διαχειριστή μνήμης, οι μεγάλοι κάδοι ξεκινούν από το σημείο όπου τελειώνουν οι μικροί κάδοι. Τα εύρη για τους μεγάλους κάδους μεγαλώνουν σταδιακά, πράγμα που σημαίνει ότι ο πρώτος κάδος μπορεί να καλύπτει κομμάτια από 512 έως 576 bytes, ενώ ο επόμενος καλύπτει από 576 έως 640 bytes. Αυτό το πρότυπο συνεχίζεται, με τον μεγαλύτερο κάδο να περιέχει όλα τα κομμάτια άνω των 1MB.
Οι μεγάλοι κάδοι είναι πιο αργοί στη λειτουργία σε σύγκριση με τους μικρούς κάδους επειδή πρέπει **να ταξινομήσουν και να αναζητήσουν μέσω μιας λίστας με διαφορετικά μεγέθη κομματιών γιανα βρουν την καλύτερη ταιριάστηκη**για μια δέσμευση. Όταν ένα κομμάτι εισάγεται σε έναν μεγάλο κάδο, πρέπει να ταξινομηθεί, και όταν γίνεται δέσμευση μνήμης, το σύστημα πρέπει να βρει το σωστό κομμάτι. Αυτή η επιπλέον εργασία τους καθιστά **πιο αργούς**, αλλά επειδή οι μεγάλες δεσμεύσεις είναι λιγότερο συνηθισμένες από τις μικρές, είναι ένα αποδεκτό ανταλλάγμα.
Υπάρχουν:
* 32 κάδοι εύρους 64B (συγκρούονται με τους μικρούς κάδους)
* 16 κάδοι εύρους 512B (συγκρούονται με τους μικρούς κάδους)
* 8 κάδοι εύρους 4096B (μέρος συγκρούεται με τους μικρούς κάδους)
* 4 κάδοι εύρους 32768B
* 2 κάδοι εύρους 262144B
* 1 κάδος για υπενθυμίζοντα μεγέθη
<details>
<summary>Κώδικας μεγέθους μεγάλων κάδων</summary>
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
<summary>Προσθέστε ένα παράδειγμα μεγάλου κομματιού</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[2];
chunks[0] = malloc(0x1500);
chunks[1] = malloc(0x1500);
free(chunks[0]);
chunks[0] = malloc(0x2000);
return 0;
}
```
Πραγματοποιούνται 2 μεγάλες δεσμεύσεις μνήμης, στη συνέχεια μια από αυτές απελευθερώνεται (τοποθετώντας τη στον unsorted κάδο) και γίνεται μια μεγαλύτερη δέσμευση (μετακινώντας την ελεύθερη στοιχειώδη από τον unsorted κάδο στον μεγάλο κάδο).
Μεταγλωττίστε το και αποσφαλματώστε το με ένα σημείο διακοπής στον κωδικό επιστροφής (ret opcode) από την κύρια συνάρτηση. Στη συνέχεια, με το gef μπορείτε να δείτε τον tcache κάδο γεμάτο και το ένα κομμάτι στον μεγάλο κάδο:
```bash
gef➤ heap bin
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
All tcachebins are empty
───────────────────────────────────────────────────────────────────────── Fastbins for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────────
Fastbins[idx=0, size=0x20] 0x00
Fastbins[idx=1, size=0x30] 0x00
Fastbins[idx=2, size=0x40] 0x00
Fastbins[idx=3, size=0x50] 0x00
Fastbins[idx=4, size=0x60] 0x00
Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] Found 0 chunks in 0 small non-empty bins.
──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
Top
The top-most available chunk (i.e., the one bordering the end of
available memory) is treated specially. It is never included in
any bin, is used only if no other chunk is available, and is
released back to the system if it is very large (see
M_TRIM_THRESHOLD). Because top initially
points to its own bin with initial zero size, thus forcing
extension on the first malloc request, we avoid having any special
code in malloc to check whether it even exists yet. But we still
need to do so when getting memory from system, so we make
initial_top treat the bin as a legal but unusable chunk during the
interval between initialization and the first call to
sysmalloc. (This is somewhat delicate, since it relies on
the 2 preceding words to be zero during this interval as well.)
*/
/* Conveniently, the unsorted bin can be used as dummy top on first call */
#define initial_top(M) (unsorted_chunks (M))
```
Βασικά, αυτό είναι ένα τμήμα που περιέχει όλο το διαθέσιμο στη στοίβα. Όταν γίνεται ένα malloc, αν δεν υπάρχει κάποιο διαθέσιμο ελεύθερο τμήμα για χρήση, αυτό το κορυφαίο τμήμα θα μειώνει το μέγεθός του δίνοντας τον απαραίτητο χώρο.\
Ο δείκτης προς το Κορυφαίο Τμήμα αποθηκεύεται στη δομή `malloc_state`.
Επιπλέον, στην αρχή, είναι δυνατόν να χρησιμοποιηθεί το μη ταξινομημένο τμήμα ως κορυφαίο τμήμα.
<details>
<summary>Παρατηρήστε το παράδειγμα του Κορυφαίου Τμήματος</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
return 0;
}
```
Μετά τη μεταγλώττιση και αποσφαλμάτωσή του με ένα σημείο διακοπής στον κωδικό επιστροφής του main, είδα ότι το malloc επέστρεψε τη διεύθυνση: `0xaaaaaaac12a0` και αυτά είναι τα κομμάτια:
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk
```
Εκεί που μπορεί να φανεί ότι το κορυφαίο κομμάτι βρίσκεται στη διεύθυνση `0xaaaaaaac1ae0`. Αυτό δεν είναι έκπληξη επειδή το τελευταίο εκχωρημένο κομμάτι ήταν στη διεύθυνση `0xaaaaaaac12a0` με μέγεθος `0x410` και `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0`.\
Είναι επίσης δυνατό να δείτε το μήκος του κορυφαίου κομματιού στην κεφαλίδα του κομματιού του:
Όταν χρησιμοποιείται το malloc και ένα κομμάτι διαιρείται (από τη λίστα μη συνδεδεμένων κομματιών ή από το κομμάτι στην κορυφή για παράδειγμα), το κομμάτι που δημιουργείται από το υπόλοιπο του διαιρεμένου κομματιού ονομάζεται Τελευταία Υπενθύμιση και ο δείκτης του αποθηκεύεται στη δομή `malloc_state`.
<summary><strong>Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Άλλοι τρόποι υποστήριξης του HackTricks:
*Αν θέλετε να δείτε την **εταιρεία σας διαφημισμένη στο HackTricks** ή να**κατεβάσετε το HackTricks σε μορφή PDF** ελέγξτε τα [**ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ**](https://github.com/sponsors/carlospolop)!
* Αποκτήστε το [**επίσημο PEASS & HackTricks swag**](https://peass.creator-spring.com)
* Ανακαλύψτε [**την Οικογένεια PEASS**](https://opensea.io/collection/the-peass-family), τη συλλογή μας από αποκλειστικά [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Εγγραφείτε στη** 💬 [**ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στη [**ομάδα telegram**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Μοιραστείτε τα χάκινγκ κόλπα σας υποβάλλοντας PRs στα** [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) αποθετήρια στο GitHub.