mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/libc-heap/unsorted-bin-attack.md']
This commit is contained in:
parent
91435b4584
commit
3ba1d18144
@ -4,52 +4,109 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
Για περισσότερες πληροφορίες σχετικά με το τι είναι ένα unsorted bin, ελέγξτε αυτή τη σελίδα:
|
||||
For more information about what is an unsorted bin check this page:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
bins-and-memory-allocations.md
|
||||
{{#endref}}
|
||||
|
||||
Οι unsorted λίστες είναι ικανές να γράφουν τη διεύθυνση στο `unsorted_chunks (av)` στη διεύθυνση `bk` του chunk. Επομένως, αν ένας επιτιθέμενος μπορεί να **τροποποιήσει τη διεύθυνση του δείκτη `bk`** σε ένα chunk μέσα στο unsorted bin, θα μπορούσε να **γράψει αυτή τη διεύθυνση σε μια αυθαίρετη διεύθυνση** που θα μπορούσε να είναι χρήσιμη για να διαρρεύσει διευθύνσεις Glibc ή να παρακάμψει κάποια άμυνα.
|
||||
Unsorted lists are able to write the address to `unsorted_chunks (av)` in the `bk` address of the chunk. Therefore, if an attacker can **modify the address of the `bk` pointer** in a chunk inside the unsorted bin, he could be able to **write that address in an arbitrary address** which could be helpful to leak a Glibc addresses or bypass some defense.
|
||||
|
||||
Έτσι, βασικά, αυτή η επίθεση επιτρέπει να **οριστεί ένας μεγάλος αριθμός σε μια αυθαίρετη διεύθυνση**. Αυτός ο μεγάλος αριθμός είναι μια διεύθυνση, η οποία θα μπορούσε να είναι μια διεύθυνση heap ή μια διεύθυνση Glibc. Ένας τυπικός στόχος είναι **`global_max_fast`** για να επιτρέψει τη δημιουργία fast bin bins με μεγαλύτερα μεγέθη (και να περάσει από μια επίθεση unsorted bin σε μια επίθεση fast bin).
|
||||
So, basically, this attack allows to **set a big number at an arbitrary address**. This big number is an address, which could be a heap address or a Glibc address. A traditional target was **`global_max_fast`** to allow to create fast bin bins with bigger sizes (and pass from an unsorted bin attack to a fast bin attack).
|
||||
|
||||
- Modern note (glibc ≥ 2.39): `global_max_fast` became an 8‑bit global. Blindly writing a pointer there via an unsorted-bin write will clobber adjacent libc data and will not reliably raise the fastbin limit anymore. Prefer other targets or other primitives when running against glibc 2.39+. See "Modern constraints" below and consider combining with other techniques like a [large bin attack](large-bin-attack.md) or a [fast bin attack](fast-bin-attack.md) once you have a stable primitive.
|
||||
|
||||
> [!TIP]
|
||||
> Ρ> ίξτε μια ματιά στο παράδειγμα που παρέχεται στο [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) και χρησιμοποιώντας 0x4000 και 0x5000 αντί για 0x400 και 0x500 ως μεγέθη chunk (για να αποφευχθεί το Tcache) είναι δυνατόν να δείτε ότι **σήμερα** το σφάλμα **`malloc(): unsorted double linked list corrupted`** ενεργοποιείται.
|
||||
> T> aking a look to the example provided in [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) and using 0x4000 and 0x5000 instead of 0x400 and 0x500 as chunk sizes (to avoid Tcache) it's possible to see that **nowadays** the error **`malloc(): unsorted double linked list corrupted`** is triggered.
|
||||
>
|
||||
> Επομένως, αυτή η επίθεση unsorted bin τώρα (μεταξύ άλλων ελέγχων) απαιτεί επίσης να είναι δυνατή η διόρθωση της διπλής συνδεδεμένης λίστας ώστε να παρακαμφθεί `victim->bk->fd == victim` ή όχι `victim->fd == av (arena)`, που σημαίνει ότι η διεύθυνση όπου θέλουμε να γράψουμε πρέπει να έχει τη διεύθυνση του ψεύτικου chunk στη θέση `fd` της και ότι το ψεύτικο chunk `fd` δείχνει στην αρένα.
|
||||
> Therefore, this unsorted bin attack now (among other checks) also requires to be able to fix the doubled linked list so this is bypassed `victim->bk->fd == victim` or not `victim->fd == av (arena)`, which means that the address where we want to write must have the address of the fake chunk in its `fd` position and that the fake chunk `fd` is pointing to the arena.
|
||||
|
||||
> [!CAUTION]
|
||||
> Σημειώστε ότι αυτή η επίθεση διαφθείρει το unsorted bin (άρα και το μικρό και το μεγάλο). Έτσι, μπορούμε μόνο να **χρησιμοποιήσουμε allocations από το fast bin τώρα** (ένα πιο περίπλοκο πρόγραμμα μπορεί να κάνει άλλες allocations και να καταρρεύσει), και για να ενεργοποιηθεί αυτό πρέπει να **κατανεμηθεί το ίδιο μέγεθος ή το πρόγραμμα θα καταρρεύσει.**
|
||||
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **allocate the same size or the program will crash.**
|
||||
>
|
||||
> Σημειώστε ότι η επαναγραφή του **`global_max_fast`** μπορεί να βοηθήσει σε αυτή την περίπτωση, εμπιστευόμενοι ότι το fast bin θα είναι σε θέση να φροντίσει όλες τις άλλες allocations μέχρι να ολοκληρωθεί η εκμετάλλευση.
|
||||
> Note that overwriting **`global_max_fast`** might help in this case trusting that the fast bin will be able to take care of all the other allocations until the exploit is completed.
|
||||
|
||||
Ο κώδικας από [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) το εξηγεί πολύ καλά, αν και αν τροποποιήσετε τις mallocs για να κατανεμηθεί μνήμη αρκετά μεγάλη ώστε να μην καταλήξει σε Tcache, μπορείτε να δείτε ότι το προηγουμένως αναφερόμενο σφάλμα εμφανίζεται, αποτρέποντας αυτή την τεχνική: **`malloc(): unsorted double linked list corrupted`**
|
||||
The code from [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explains it very well, although if you modify the mallocs to allocate memory big enough so don't end in a Tcache you can see that the previously mentioned error appears preventing this technique: **`malloc(): unsorted double linked list corrupted`**
|
||||
|
||||
### How the write actually happens
|
||||
|
||||
- The unsorted-bin write is triggered on `free` when the freed chunk is inserted at the head of the unsorted list.
|
||||
- During insertion, the allocator performs `bck = unsorted_chunks(av); fwd = bck->fd; victim->bk = bck; victim->fd = fwd; fwd->bk = victim; bck->fd = victim;`
|
||||
- If you can set `victim->bk` to `(mchunkptr)(TARGET - 0x10)` before calling `free(victim)`, the final statement will perform the write: `*(TARGET) = victim`.
|
||||
- Later, when the allocator processes the unsorted bin, integrity checks will verify (among other things) that `bck->fd == victim` and `victim->fd == unsorted_chunks(av)` before unlinking. Because the insertion already wrote `victim` into `bck->fd` (our `TARGET`), these checks can be satisfied if the write succeeded.
|
||||
|
||||
## Modern constraints (glibc ≥ 2.33)
|
||||
|
||||
To use unsorted‑bin writes reliably on current glibc:
|
||||
|
||||
- Tcache interference: for sizes that fall into tcache, frees are diverted there and won’t touch the unsorted bin. Either
|
||||
- make requests with sizes > MAX_TCACHE_SIZE (≥ 0x410 on 64‑bit by default), or
|
||||
- fill the corresponding tcache bin (7 entries) so that additional frees reach the global bins, or
|
||||
- if the environment is controllable, disable tcache (e.g., GLIBC_TUNABLES glibc.malloc.tcache_count=0).
|
||||
- Integrity checks on the unsorted list: on the next allocation path that examines the unsorted bin, glibc checks (simplified):
|
||||
- `bck->fd == victim` and `victim->fd == unsorted_chunks(av)`; otherwise it aborts with `malloc(): unsorted double linked list corrupted`.
|
||||
- This means the address you target must tolerate two writes: first `*(TARGET) = victim` at free‑time; later, as the chunk is removed, `*(TARGET) = unsorted_chunks(av)` (the allocator rewrites `bck->fd` back to the bin head). Choose targets where simply forcing a large non‑zero value is useful.
|
||||
- Typical stable targets in modern exploits
|
||||
- Application or global state that treats "large" values as flags/limits.
|
||||
- Indirect primitives (e.g., set up for a subsequent [fast bin attack]({{#ref}}fast-bin-attack.md{{#endref}}) or to pivot a later write‐what‐where).
|
||||
- Avoid `__malloc_hook`/`__free_hook` on new glibc: they were removed in 2.34. Avoid `global_max_fast` on ≥ 2.39 (see next note).
|
||||
- About `global_max_fast` on recent glibc
|
||||
- On glibc 2.39+, `global_max_fast` is an 8‑bit global. The classic trick of writing a heap pointer into it (to enlarge fastbins) no longer works cleanly and is likely to corrupt adjacent allocator state. Prefer other strategies.
|
||||
|
||||
## Minimal exploitation recipe (modern glibc)
|
||||
|
||||
Goal: achieve a single arbitrary write of a heap pointer to an arbitrary address using the unsorted‑bin insertion primitive, without crashing.
|
||||
|
||||
- Layout/grooming
|
||||
- Allocate A, B, C with sizes large enough to bypass tcache (e.g., 0x5000). C prevents consolidation with the top chunk.
|
||||
- Corruption
|
||||
- Overflow from A into B’s chunk header to set `B->bk = (mchunkptr)(TARGET - 0x10)`.
|
||||
- Trigger
|
||||
- `free(B)`. At insertion time the allocator executes `bck->fd = B`, therefore `*(TARGET) = B`.
|
||||
- Continuation
|
||||
- If you plan to continue allocating and the program uses the unsorted bin, expect the allocator to later set `*(TARGET) = unsorted_chunks(av)`. Both values are typically large and may be enough to change size/limit semantics in targets that only check for "big".
|
||||
|
||||
Σκελετός ψευδοκώδικα:
|
||||
```c
|
||||
// 64-bit glibc 2.35–2.38 style layout (tcache bypass via large sizes)
|
||||
void *A = malloc(0x5000);
|
||||
void *B = malloc(0x5000);
|
||||
void *C = malloc(0x5000); // guard
|
||||
|
||||
// overflow from A into B’s metadata (prev_size/size/.../bk). You must control B->bk.
|
||||
*(size_t *)((char*)B - 0x8) = (size_t)(TARGET - 0x10); // write fake bk
|
||||
|
||||
free(B); // triggers *(TARGET) = B (unsorted-bin insertion write)
|
||||
```
|
||||
> [!NOTE]
|
||||
> • Αν δεν μπορείτε να παρακάμψετε το tcache με το μέγεθος, γεμίστε το tcache bin για το επιλεγμένο μέγεθος (7 frees) πριν απελευθερώσετε το διεφθαρμένο chunk ώστε το free να πάει στο unsorted.
|
||||
> • Αν το πρόγραμμα τερματίζει αμέσως στην επόμενη allocation λόγω των ελέγχων unsorted-bin, επανεξετάστε ότι `victim->fd` εξακολουθεί να ισούται με το bin head και ότι το `TARGET` σας κρατάει τον ακριβή δείκτη `victim` μετά το πρώτο write.
|
||||
|
||||
## Unsorted Bin Infoleak Attack
|
||||
|
||||
Αυτό είναι στην πραγματικότητα μια πολύ βασική έννοια. Τα chunks στο unsorted bin θα έχουν δείκτες. Το πρώτο chunk στο unsorted bin θα έχει στην πραγματικότητα τους συνδέσμους **`fd`** και **`bk`** **να δείχνουν σε ένα μέρος της κύριας αρένας (Glibc)**.\
|
||||
Επομένως, αν μπορείτε να **βάλτε ένα chunk μέσα σε ένα unsorted bin και να το διαβάσετε** (use after free) ή **να το κατανεμηθείτε ξανά χωρίς να επαναγράψετε τουλάχιστον 1 από τους δείκτες** για να **το διαβάσετε**, μπορείτε να έχετε μια **Glibc info leak**.
|
||||
Αυτή είναι στην ουσία μια πολύ βασική ιδέα. Τα chunks στο unsorted bin θα έχουν pointers. Το πρώτο chunk στο unsorted bin θα έχει στην πραγματικότητα τους συνδέσμους **`fd`** και **`bk`** **που δείχνουν σε ένα μέρος του main arena (Glibc)**.\
|
||||
Επομένως, αν μπορείτε **να βάλετε ένα chunk μέσα σε ένα unsorted bin και να το διαβάσετε** (use after free) ή **να το allocate ξανά χωρίς να υπερχρεώσετε τουλάχιστον έναν από τους pointers** και μετά να το **read**, μπορείτε να έχετε ένα **Glibc info leak**.
|
||||
|
||||
Μια παρόμοια [**επίθεση που χρησιμοποιήθηκε σε αυτή την αναφορά**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), ήταν να καταχραστεί μια δομή 4 chunks (A, B, C και D - D είναι μόνο για να αποτρέψει τη συγχώνευση με το top chunk) έτσι ώστε μια υπερχείλιση null byte στο B να χρησιμοποιηθεί για να κάνει το C να υποδείξει ότι το B ήταν αχρησιμοποίητο. Επίσης, στο B τα δεδομένα `prev_size` τροποποιήθηκαν έτσι ώστε το μέγεθος αντί να είναι το μέγεθος του B να είναι A+B.\
|
||||
Στη συνέχεια, το C απελευθερώθηκε και συγχωνεύθηκε με A+B (αλλά το B ήταν ακόμα σε χρήση). Ένα νέο chunk μεγέθους A κατανεμήθηκε και στη συνέχεια οι διευθύνσεις libc διαρρεύθηκαν στο B από όπου διαρρεύθηκαν.
|
||||
A similar [**attack used in this writeup**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), ήταν να εκμεταλλευτούν μια δομή 4 chunks (A, B, C και D - το D υπάρχει μόνο για να αποτρέψει τη συγχώνευση με το top chunk) έτσι ώστε ένα null byte overflow στο B να χρησιμοποιηθεί για να κάνει το C να δείχνει ότι το B ήταν unused. Επίσης, στο B τα δεδομένα `prev_size` τροποποιήθηκαν ώστε το μέγεθος, αντί να είναι το μέγεθος του B, να είναι A+B.\
|
||||
Έπειτα το C απελευθερώθηκε και συγχωνεύθηκε με το A+B (αλλά το B ήταν ακόμα in use). Ένα νέο chunk μεγέθους A διατέθηκε και τότε οι libc leaked addresses γράφτηκαν στο B από όπου έγιναν leak.
|
||||
|
||||
## References & Other examples
|
||||
## Αναφορές & Άλλα παραδείγματα
|
||||
|
||||
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap)
|
||||
- Ο στόχος είναι να επαναγραφεί μια παγκόσμια μεταβλητή με μια τιμή μεγαλύτερη από 4869 ώστε να είναι δυνατή η λήψη της σημαίας και το PIE να μην είναι ενεργοποιημένο.
|
||||
- Είναι δυνατή η δημιουργία chunks αυθαίρετου μεγέθους και υπάρχει μια υπερχείλιση heap με το επιθυμητό μέγεθος.
|
||||
- Η επίθεση ξεκινά δημιουργώντας 3 chunks: chunk0 για να καταχραστεί την υπερχείλιση, chunk1 για να υπερχυθεί και chunk2 ώστε το top chunk να μην συγχωνευθεί με τα προηγούμενα.
|
||||
- Στη συνέχεια, το chunk1 απελευθερώνεται και το chunk0 υπερχύνεται ώστε ο δείκτης `bk` του chunk1 να δείχνει: `bk = magic - 0x10`
|
||||
- Στη συνέχεια, το chunk3 κατανεμήθηκε με το ίδιο μέγεθος όπως το chunk1, το οποίο θα ενεργοποιήσει την επίθεση unsorted bin και θα τροποποιήσει την τιμή της παγκόσμιας μεταβλητής, καθιστώντας δυνατή τη λήψη της σημαίας.
|
||||
- Ο στόχος είναι να overwrite μια global μεταβλητή με μια τιμή μεγαλύτερη του 4869 ώστε να είναι δυνατόν να πάρεις το flag και το PIE να μην είναι ενεργοποιημένο.
|
||||
- Είναι δυνατό να δημιουργηθούν chunks αυθαίρετων μεγεθών και υπάρχει μια heap overflow με το επιθυμητό μέγεθος.
|
||||
- Η επίθεση ξεκινά δημιουργώντας 3 chunks: chunk0 για να εκμεταλλευτεί την overflow, chunk1 που θα overflow-αριστεί και chunk2 ώστε το top chunk να μην συγχωνεύσει τα προηγούμενα.
|
||||
- Στη συνέχεια, το chunk1 αποδεσμεύεται (freed) και το chunk0 overflow-άρεται ώστε το `bk` pointer του chunk1 να δείχνει σε: `bk = magic - 0x10`
|
||||
- Έπειτα, το chunk3 διατίθεται με το ίδιο μέγεθος όπως το chunk1, το οποίο θα ενεργοποιήσει το unsorted bin attack και θα τροποποιήσει την τιμή της global μεταβλητής, καθιστώντας δυνατό το flag.
|
||||
- [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html)
|
||||
- Η συνάρτηση merge είναι ευάλωτη επειδή αν και οι δύο δείκτες που περάστηκαν είναι ο ίδιος, θα επανακατανεμηθεί σε αυτόν και στη συνέχεια θα απελευθερωθεί, αλλά επιστρέφει έναν δείκτη σε αυτήν την απελευθερωμένη περιοχή που μπορεί να χρησιμοποιηθεί.
|
||||
- Επομένως, **δημιουργούνται 2 chunks**: **chunk0** το οποίο θα συγχωνευθεί με τον εαυτό του και chunk1 για να αποτρέψει τη συγχώνευση με το top chunk. Στη συνέχεια, η **συνάρτηση merge καλείται με το chunk0** δύο φορές, γεγονός που θα προκαλέσει χρήση μετά την απελευθέρωση.
|
||||
- Στη συνέχεια, η **συνάρτηση `view`** καλείται με δείκτη 2 (ο οποίος είναι ο δείκτης του chunk που χρησιμοποιήθηκε μετά την απελευθέρωση), το οποίο θα **διαρρεύσει μια διεύθυνση libc**.
|
||||
- Καθώς το δυαδικό έχει προστασίες για να επιτρέπει μόνο malloc μεγέθη μεγαλύτερα από **`global_max_fast`**, δεν χρησιμοποιείται κανένα fastbin, θα χρησιμοποιηθεί μια επίθεση unsorted bin για να επαναγραφεί η παγκόσμια μεταβλητή `global_max_fast`.
|
||||
- Στη συνέχεια, είναι δυνατή η κλήση της συνάρτησης edit με τον δείκτη 2 (τον δείκτη του pointer που χρησιμοποιήθηκε μετά την απελευθέρωση) και να επαναγραφεί ο δείκτης `bk` ώστε να δείχνει σε `p64(global_max_fast-0x10)`. Στη συνέχεια, η δημιουργία ενός νέου chunk θα χρησιμοποιήσει τη προηγουμένως παραβιασμένη ελεύθερη διεύθυνση (0x20) που θα **ενεργοποιήσει την επίθεση unsorted bin** επαναγράφοντας το `global_max_fast` με μια πολύ μεγάλη τιμή, επιτρέποντας τώρα τη δημιουργία chunks σε fast bins.
|
||||
- Τώρα εκτελείται μια **επίθεση fast bin**:
|
||||
- Πρώτα απ 'όλα, ανακαλύπτεται ότι είναι δυνατό να εργαστείτε με γρήγορες **chunks μεγέθους 200** στη θέση **`__free_hook`**:
|
||||
- Η συνάρτηση merge είναι ευάλωτη επειδή αν περάσουν και τα δύο indexes το ίδιο, τότε θα κάνει realloc σε αυτό και μετά free αλλά επιστρέφει έναν pointer σε αυτή τη freed περιοχή που μπορεί να χρησιμοποιηθεί.
|
||||
- Επομένως, **δημιουργούνται 2 chunks**: **chunk0** το οποίο θα συγχωνευτεί με τον εαυτό του και chunk1 για να αποτρέψει τη συγχώνευση με το top chunk. Μετά, η συνάρτηση **merge** καλείται με το chunk0 δύο φορές, πράγμα που προκαλεί use after free.
|
||||
- Έπειτα, η συνάρτηση **`view`** καλείται με index 2 (που είναι ο index του use after free chunk), το οποίο θα **leak** μια libc address.
|
||||
- Καθώς το binary έχει προστασίες ώστε να κάνει malloc μόνο για μεγέθη μεγαλύτερα από το **`global_max_fast`** οπότε δεν χρησιμοποιείται fastbin, θα χρησιμοποιηθεί μια unsorted bin attack για να overwrite-αριστεί η global μεταβλητή `global_max_fast`.
|
||||
- Μετά, είναι δυνατό να καλέσεις τη συνάρτηση edit με το index 2 (το pointer του use after free) και να υπερχαρακτήσεις τον pointer `bk` ώστε να δείχνει σε `p64(global_max_fast-0x10)`. Έπειτα, η δημιουργία ενός νέου chunk θα χρησιμοποιήσει τη προηγουμένως παραβιασμένη free διεύθυνση (0x20) και θα **trigger** το unsorted bin attack, overwriting το `global_max_fast` με μια πολύ μεγάλη τιμή, επιτρέποντας πλέον τη δημιουργία chunks σε fast bins.
|
||||
- Τώρα εκτελείται μια **fast bin attack**:
|
||||
- Αρχικά ανακαλύπτεται ότι είναι δυνατό να λειτουργήσουμε με fast chunks μεγέθους 200 στη θέση του **`__free_hook`**:
|
||||
- <pre class="language-c"><code class="lang-c">gef➤ p &__free_hook
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
@ -58,16 +115,20 @@ gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
</code></pre>
|
||||
- Αν καταφέρουμε να αποκτήσουμε ένα γρήγορο chunk μεγέθους 0x200 σε αυτή τη θέση, θα είναι δυνατό να επαναγράψουμε έναν δείκτη συνάρτησης που θα εκτελείται
|
||||
- Για αυτό, δημιουργείται ένα νέο chunk μεγέθους `0xfc` και η συνάρτηση merged καλείται με αυτόν τον δείκτη δύο φορές, με αυτόν τον τρόπο αποκτούμε έναν δείκτη σε ένα ελεύθερο chunk μεγέθους `0xfc*2 = 0x1f8` στο fast bin.
|
||||
- Στη συνέχεια, η συνάρτηση edit καλείται σε αυτό το chunk για να τροποποιήσει τη διεύθυνση **`fd`** αυτού του fast bin ώστε να δείχνει στην προηγούμενη συνάρτηση **`__free_hook`**.
|
||||
- Στη συνέχεια, δημιουργείται ένα chunk μεγέθους `0x1f8` για να ανακτηθεί από το fast bin το προηγούμενο άχρηστο chunk, ώστε να δημιουργηθεί ένα άλλο chunk μεγέθους `0x1f8` για να αποκτήσει ένα fast bin chunk στη **`__free_hook`** το οποίο επαναγράφεται με τη διεύθυνση της συνάρτησης **`system`**.
|
||||
- Και τελικά, ένα chunk που περιέχει τη συμβολοσειρά `/bin/sh\x00` απελευθερώνεται καλώντας τη συνάρτηση delete, ενεργοποιώντας τη συνάρτηση **`__free_hook`** που δείχνει στη συνάρτηση system με `/bin/sh\x00` ως παράμετρο.
|
||||
- Αν καταφέρουμε να έχουμε ένα fast chunk μεγέθους 0x200 σε αυτή τη θέση, θα είναι δυνατό να overwrite-αριστεί ένας function pointer που θα εκτελεστεί.
|
||||
- Για αυτό, δημιουργείται ένα νέο chunk μεγέθους `0xfc` και η συνάρτηση merged καλείται με αυτόν τον pointer δύο φορές, έτσι λαμβάνουμε έναν pointer σε freed chunk μεγέθους `0xfc*2 = 0x1f8` στο fast bin.
|
||||
- Έπειτα, η συνάρτηση edit καλείται σε αυτό το chunk για να τροποποιήσει τη διεύθυνση **`fd`** αυτού του fast bin ώστε να δείχνει στο προηγούμενο **`__free_hook`**.
|
||||
- Μετά, δημιουργείται ένα chunk με μέγεθος `0x1f8` για να ανακτήσει από το fast bin το προηγούμενο άχρηστο chunk και στη συνέχεια δημιουργείται άλλο ένα chunk μεγέθους `0x1f8` για να πάρει ένα fast bin chunk στο **`__free_hook`** το οποίο και overwritten-άρεται με τη διεύθυνση της συνάρτησης **`system`**.
|
||||
- Και τελικά, ένα chunk που περιέχει τη συμβολοσειρά `/bin/sh\x00` απελευθερώνεται καλώντας τη delete function, ενεργοποιώντας το **`__free_hook`** που δείχνει στο system με παράμετρο το `/bin/sh\x00`.
|
||||
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
|
||||
- Ένα άλλο παράδειγμα κατάχρησης μιας υπερχείλισης 1B για να συγχωνευθούν chunks στο unsorted bin και να αποκτηθεί μια libc infoleak και στη συνέχεια να εκτελεστεί μια επίθεση fast bin για να επαναγραφεί το malloc hook με μια διεύθυνση one gadget
|
||||
- Ένα άλλο παράδειγμα εκμετάλλευσης ενός 1B overflow για να συγχωνευτούν chunks στο unsorted bin και να ληφθεί ένα libc infoleak και στη συνέχεια να γίνει fast bin attack για να overwrite-αριστεί το malloc hook με μια one gadget διεύθυνση
|
||||
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
|
||||
- Μπορούμε να κατανεμηθούν μόνο chunks μεγέθους μεγαλύτερου από `0x100`.
|
||||
- Επαναγράψτε το `global_max_fast` χρησιμοποιώντας μια επίθεση Unsorted Bin (λειτουργεί 1/16 φορές λόγω ASLR, επειδή πρέπει να τροποποιήσουμε 12 bits, αλλά πρέπει να τροποποιήσουμε 16 bits).
|
||||
- Επίθεση Fast Bin για να τροποποιηθεί μια παγκόσμια σειρά chunks. Αυτό δίνει μια αυθαίρετη ανάγνωση/γραφή primitive, που επιτρέπει την τροποποίηση του GOT και την ρύθμιση κάποιων συναρτήσεων να δείχνουν στη `system`.
|
||||
- Μπορούμε να κάνουμε allocate μόνο chunks με μέγεθος μεγαλύτερο του `0x100`.
|
||||
- Overwrite του `global_max_fast` χρησιμοποιώντας Unsorted Bin attack (λειτουργεί 1/16 φορές λόγω ASLR, επειδή πρέπει να τροποποιήσουμε 12 bits, αλλά ουσιαστικά πρέπει να τροποποιήσουμε 16 bits).
|
||||
- Fast Bin attack για να τροποποιηθεί ένας global πίνακας από chunks. Αυτό δίνει ένα arbitrary read/write primitive, που επιτρέπει να τροποποιηθεί το GOT και να δείξει κάποια συνάρτηση στο `system`.
|
||||
|
||||
## Αναφορές
|
||||
|
||||
- Glibc malloc unsorted-bin integrity checks (example in 2.33 source): https://elixir.bootlin.com/glibc/glibc-2.33/source/malloc/malloc.c
|
||||
- `global_max_fast` and related definitions in modern glibc (2.39): https://elixir.bootlin.com/glibc/glibc-2.39/source/malloc/malloc.c
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user