House of Roman

Υποστήριξε το HackTricks

Βασικές Πληροφορίες

Αυτή ήταν μια πολύ ενδιαφέρουσα τεχνική που επέτρεπε την RCE χωρίς διαρροές μέσω ψεύτικων fastbins, επίθεση στο unsorted_bin και σχετικές αντικαταστάσεις. Ωστόσο, έχει διορθωθεί.

Κώδικας

Στόχος

  • RCE με κατάχρηση σχετικών δεικτών

Απαιτήσεις

  • Επεξεργασία δεικτών fastbin και unsorted bin

  • Πρέπει να υπάρχουν 12 bits τυχαιότητας που πρέπει να αναγκαστούν (πιθανότητα 0,02%) να λειτουργήσουν

Βήματα Επίθεσης

Μέρος 1: Το Fastbin Chunk δείχνει στο __malloc_hook

Δημιουργήστε αρκετά κομμάτια:

  • fastbin_victim (0x60, μετατόπιση 0): UAF κομμάτι αργότερα για να επεξεργαστείτε το δείκτη του σωρού αργότερα ώστε να δείχνει στην τιμή της LibC.

  • chunk2 (0x80, μετατόπιση 0x70): Για καλή ευθυγράμμιση

  • main_arena_use (0x80, μετατόπιση 0x100)

  • relative_offset_heap (0x60, μετατόπιση 0x190): σχετική μετατόπιση στο κομμάτι 'main_arena_use'

Στη συνέχεια, ελευθερώστε το main_arena_use, το οποίο θα τοποθετήσει αυτό το κομμάτι στη λίστα unsorted και θα λάβει ένα δείκτη στο main_arena + 0x68 τόσο στους δείκτες fd όσο και bk.

Τώρα δεσμεύεται ένα νέο κομμάτι fake_libc_chunk(0x60) επειδή θα περιέχει τους δείκτες στο main_arena + 0x68 στους fd και bk.

Στη συνέχεια, ελευθερώνονται τα relative_offset_heap και fastbin_victim.

/*
Current heap layout:
0x0:   fastbin_victim       - size 0x70
0x70:  alignment_filler     - size 0x90
0x100: fake_libc_chunk      - size 0x70 (contains a fd ptr to main_arena + 0x68)
0x170: leftover_main        - size 0x20
0x190: relative_offset_heap - size 0x70

bin layout:
fastbin:  fastbin_victim -> relative_offset_heap
unsorted: leftover_main
*/
  • fastbin_victim έχει ένα fd που δείχνει στο relative_offset_heap

  • relative_offset_heap είναι μια μετατόπιση απόστασης από το fake_libc_chunk, το οποίο περιέχει ένα δείκτη προς το main_arena + 0x68

  • Αλλάζοντας απλά το τελευταίο byte του fastbin_victim.fd είναι δυνατό να κάνουμε το fastbin_victim να δείχνει στο main_arena + 0x68

Για τις προηγούμενες ενέργειες, ο επιτιθέμενος πρέπει να είναι ικανός να τροποποιήσει τον δείκτη fd του fastbin_victim.

Στη συνέχεια, το main_arena + 0x68 δεν είναι τόσο ενδιαφέρον, οπότε ας το τροποποιήσουμε ώστε ο δείκτης να δείχνει στο __malloc_hook.

Σημειώστε ότι το __memalign_hook συνήθως ξεκινά με 0x7f και μηδενικά πριν από αυτό, οπότε είναι δυνατό να το πλασάρουμε ως τιμή στο fast bin 0x70. Επειδή τα τελευταία 4 bits της διεύθυνσης είναι τυχαία, υπάρχουν 2^4=16 πιθανότητες για την τιμή να καταλήξει εκεί που μας ενδιαφέρει. Έτσι εδώ πραγματοποιείται μια επίθεση BF ώστε το κομμάτι να καταλήξει ως εξής: 0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23).

(Για περισσότερες πληροφορίες σχετικά με τα υπόλοιπα bytes ελέγξτε την εξήγηση στο how2heap παράδειγμα). Αν η BF δεν λειτουργήσει, το πρόγραμμα απλώς καταρρέει (οπότε ξεκινήστε ξανά μέχρι να λειτουργήσει).

Στη συνέχεια, πραγματοποιούνται 2 mallocs για να αφαιρεθούν τα 2 αρχικά fast bin chunks και στη συνέχεια γίνεται μια τρίτη κλήση για να ληφθεί ένα κομμάτι στο __malloc_hook:

malloc(0x60);
malloc(0x60);
uint8_t* malloc_hook_chunk = malloc(0x60);

Μέρος 2: Επίθεση unsorted_bin

Για περισσότερες πληροφορίες μπορείτε να ελέγξετε:

Unsorted Bin Attack

Βασικά, επιτρέπει την εγγραφή της τιμής main_arena + 0x68 σε οποιαδήποτε τοποθεσία που καθορίζεται στο chunk->bk. Και για την επίθεση επιλέγουμε το __malloc_hook. Στη συνέχεια, μετά την αντικατάστασή του, θα χρησιμοποιήσουμε μια σχετική αντικατάσταση για να δείχνει σε ένα one_gadget.

Για αυτό ξεκινάμε παίρνοντας ένα κομμάτι και το τοποθετούμε στο unsorted bin:

uint8_t* unsorted_bin_ptr = malloc(0x80);
malloc(0x30); // Don't want to consolidate

puts("Put chunk into unsorted_bin\n");
// Free the chunk to create the UAF
free(unsorted_bin_ptr);

Χρησιμοποιήστε ένα UAF σε αυτό το κομμάτι για να δείξετε το unsorted_bin_ptr->bk στη διεύθυνση του __malloc_hook (το οποίο το είχαμε υπολογίσει με brute force προηγουμένως).

Σημειώστε ότι αυτή η επίθεση διαφθείρει το unsorted bin (και τα small και large επίσης). Έτσι μπορούμε μόνο να χρησιμοποιήσουμε εκχωρήσεις από το fast bin τώρα (ένα πιο πολύπλοκο πρόγραμμα ενδέχεται να κάνει άλλες εκχωρήσεις και να καταρρεύσει), και για να ενεργοποιήσουμε αυτό πρέπει να εκχωρήσουμε τον ίδιο μέγεθος αλλιώς το πρόγραμμα θα καταρρεύσει.

Έτσι, για να ενεργοποιήσουμε την εγγραφή του main_arena + 0x68 στο __malloc_hook εκτελούμε μετά την ρύθμιση του __malloc_hook στο unsorted_bin_ptr->bk απλώς πρέπει να κάνουμε: malloc(0x80)

Βήμα 3: Ρύθμιση του __malloc_hook σε σύστημα

Στο πρώτο βήμα καταλήξαμε να ελέγχουμε ένα κομμάτι που περιέχει το __malloc_hook (στη μεταβλητή malloc_hook_chunk) και στο δεύτερο βήμα καταφέραμε να γράψουμε το main_arena + 0x68 εδώ.

Τώρα, εκμεταλλευόμαστε μια μερική επικάλυψη στο malloc_hook_chunk για να χρησιμοποιήσουμε τη διεύθυνση libc που γράψαμε εκεί (main_arena + 0x68) για να δείξουμε μια διεύθυνση one_gadget.

Εδώ είναι όπου απαιτείται να υπολογίσουμε με brute force 12 bits τυχαιότητας (περισσότερες πληροφορίες στο how2heap παράδειγμα).

Τέλος, αφού αντικατασταθεί η σωστή διεύθυνση, καλέστε το malloc και ενεργοποιήστε το one_gadget.

Αναφορές

Last updated