House of Roman

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

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

Αυτή ήταν μια πολύ ενδιαφέρουσα τεχνική που επέτρεπε RCE χωρίς leaks μέσω fake fastbins, the unsorted_bin attack και relative overwrites. Ωστόσο, έχει patched.

Εφαρμοσιμότητα το 2026

  • glibc window: Λειτουργεί αξιόπιστα σε 2.23–2.27 (το how2heap PoC δοκίμασε 2.23–2.25). Από 2.28, το patch “additional checks for unsorted bin integrity” κάνει την unsorted‑bin εγγραφή αναξιόπιστη, οπότε η επιτυχία μειώνεται δραστικά. Από 2.34 και μετά αφαιρέθηκαν τα __malloc_hook/__free_hook, καθιστώντας τον αρχικό στόχο μη διαθέσιμο. Χρησιμοποιήστε το μόνο σε παλιά libc (ή custom builds που διατηρούν τα hooks) ή για CTF challenges που περιλαμβάνουν παλιά libc.
  • Tcache era (≥2.26): Το Tcache θα “καταβροχθίσει” τις 0x70 allocations και θα σταματήσει τα fastbin/unsorted primitives. Απενεργοποιήστε το (setenv("GLIBC_TUNABLES","glibc.malloc.tcache_count=0",1);) πριν από οποιαδήποτε allocation ή γεμίστε κάθε 0x70 tcache bin με 7 frees για να το εκκενώσετε.
  • Safe-linking: Ισχύει για tcache/fastbin σε ≥2.32, αλλά το House of Roman χρειάζεται μόνο μερική υπερχείριση pointer ενός libc address που ήδη υπάρχει σε fd/bk, οπότε το safe-linking δεν βοηθάει εδώ τον αμυνόμενο (ο επιτιθέμενος ποτέ δεν κατασκευάζει νέο pointer). Ο πραγματικός αναχαιτισμός είναι η αφαίρεση των hooks και οι έλεγχοι του unsorted‑bin.

Code

Στόχος

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

Απαιτήσεις

  • Edit fastbin and unsorted bin pointers
  • 12 bits of randomness must be brute forced (0.02% chance) of working

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

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

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

  • fastbin_victim (0x60, offset 0): UAF chunk που αργότερα θα χρησιμοποιηθεί για να επεξεργαστεί ο heap pointer ώστε να δείχνει στην LibC τιμή.
  • chunk2 (0x80, offset 0x70): Για σωστή στοίχιση
  • main_arena_use (0x80, offset 0x100)
  • relative_offset_heap (0x60, offset 0x190): σχετική μετατόπιση στο ‘main_arena_use’ chunk

Στη συνέχεια κάντε free(main_arena_use) το οποίο θα τοποθετήσει αυτό το chunk στη λίστα unsorted και θα βάλει pointer προς main_arena + 0x68 τόσο στο fd όσο και στο bk.

Τώρα δεσμεύεται ένα νέο chunk fake_libc_chunk(0x60) επειδή θα περιέχει τους pointers προς 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 has a fd pointing to relative_offset_heap
  • relative_offset_heap is an offset of distance from fake_libc_chunk, which contains a pointer to main_arena + 0x68
  • Changing the last byte of fastbin_victim.fd makes fastbin_victim point to main_arena + 0x68.

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

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

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

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

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

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

Μέρος 2: Unsorted_bin attack

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

Unsorted Bin Attack

Αλλά ουσιαστικά επιτρέπει να γράψετε main_arena + 0x68 σε οποιαδήποτε θέση καθορίζεται στο chunk->bk. Για την επίθεση επιλέγουμε __malloc_hook. Στη συνέχεια, αφού το αντικαταστήσουμε, θα χρησιμοποιήσουμε ένα relative overwrite για να δείξουμε σε one_gadget.

Για αυτό αρχίζουμε να παίρνουμε ένα chunk και να το τοποθετούμε στο 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);

Use an UAF in this chunk to point unsorted_bin_ptr->bk to the address of __malloc_hook (we brute forced this previously).

Caution

Σημειώστε ότι αυτή η επίθεση διεφθείρει το unsorted bin (οπότε και small και large επίσης). Οπότε μπορούμε τώρα μόνο να use allocations from the fast bin now (ένα πιο πολύπλοκο πρόγραμμα μπορεί να κάνει άλλες allocations και να κάνει crash), και για να το ενεργοποιήσουμε πρέπει να alloc το ίδιο μέγεθος αλλιώς το πρόγραμμα θα κάνει crash.

So, to trigger the write of main_arena + 0x68 in __malloc_hook we perform after setting __malloc_hook in unsorted_bin_ptr->bk we just need to do: malloc(0x80)

Step 3: Set __malloc_hook to system

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

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

Εδώ χρειάζεται να bruteforce 12 bits of randomness (περισσότερες πληροφορίες στο how2heap example).

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

Modern tips & variants

  • Unsorted-bin hardening (2.28+): Οι επιπλέον έλεγχοι ακεραιότητας σε unsorted chunks (size sanity + list linkage) κάνουν την κλασική unsorted‑bin write ευάλωτη. Για να επιβιώσει το _int_malloc, πρέπει να διατηρήσετε τους συνδέσμους fd/bk συνεπείς και τα μεγέθη να είναι λογικά, κάτι που συνήθως απαιτεί πιο ισχυρά primitives από ένα απλό partial overwrite.
  • Hook removal (2.34+): Με το __malloc_hook να έχει αφαιρεθεί, προσαρμόστε το primitive ώστε να καταλήξει σε οποιοδήποτε writable GOT/global που μπορείτε να επαναχρησιμοποιήσετε (π.χ. overwrite exit@GOT σε non-PIE binaries) ή στρέψτε σε μια top‑chunk hijack στυλ House of Pie για να ελέγξετε το top αντί για ένα hook.
  • Any‑address fastbin alloc (romanking98 writeup): Το δεύτερο μέρος δείχνει την επισκευή της 0x71 freelist και τη χρήση του unsorted‑bin write για να φέρει μια fastbin allocation πάνω από το __free_hook, στη συνέχεια την τοποθέτηση του system("/bin/sh") και την ενεργοποίησή του μέσω free() σε libc‑2.24 (pre-hook removal).

References

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks