House of Roman

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Informazioni di base

Questa è stata una tecnica molto interessante che permetteva RCE senza leaks tramite fake fastbins, l’attacco unsorted_bin e relative overwrites. Tuttavia è stata patched.

Applicabilità nel 2026

  • glibc window: Funziona in modo affidabile su 2.23–2.27 (il PoC how2heap ha testato 2.23–2.25). A partire da 2.28, la patch “additional checks for unsorted bin integrity” rende l’unsorted‑bin write non affidabile, quindi il successo cala drasticamente. Da 2.34 in poi __malloc_hook/__free_hook sono stati rimossi, rendendo il target originale non disponibile. Usarla solo su libc vecchie (o build personalizzate che mantengono gli hook) o per CTF che forniscono una libc vecchia.
  • Tcache era (≥2.26): Tcache consumerà le tue allocazioni 0x70 e bloccherà le primitive fastbin/unsorted. Disabilitalo (setenv("GLIBC_TUNABLES","glibc.malloc.tcache_count=0",1);) prima di qualsiasi allocazione oppure riempi ogni bin tcache da 0x70 con 7 free per svuotarlo.
  • Safe-linking: Si applica a tcache/fastbin in ≥2.32, ma House of Roman necessita solo di un partial pointer overwrite of a libc address already present in fd/bk, quindi safe-linking non aiuta il difensore qui (l’attaccante non forgia mai un puntatore nuovo). Il vero ostacolo è la rimozione degli hook e i controlli sull’unsorted-bin.

Codice

Obiettivo

  • RCE sfruttando puntatori relativi

Requisiti

  • Modificare i puntatori fastbin e unsorted bin
  • È necessario forzare 12 bit di randomness (probabilità di successo 0.02%)

Fasi dell’attacco

Parte 1: Fastbin Chunk punta a __malloc_hook

Crea diversi chunk:

  • fastbin_victim (0x60, offset 0): chunk UAF da editare dopo per puntare il puntatore heap al valore libc.
  • chunk2 (0x80, offset 0x70): per un buon allineamento
  • main_arena_use (0x80, offset 0x100)
  • relative_offset_heap (0x60, offset 0x190): offset relativo sul chunk ‘main_arena_use’

Poi free(main_arena_use) che metterà questo chunk nella lista unsorted e popolerà sia fd che bk con un puntatore a main_arena + 0x68.

Ora viene allocato un nuovo chunk fake_libc_chunk(0x60) perché conterrà i puntatori a main_arena + 0x68 in fd e bk.

Poi vengono fatti free di relative_offset_heap e 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 ha un fd che punta a relative_offset_heap
  • relative_offset_heap è un offset di distanza da fake_libc_chunk, che contiene un puntatore a main_arena + 0x68
  • Cambiare l’ultimo byte di fastbin_victim.fd fa sì che fastbin_victim punti a main_arena + 0x68.

Per le azioni precedenti, l’attaccante deve essere in grado di modificare il puntatore fd di fastbin_victim.

Poi, main_arena + 0x68 non è molto interessante, quindi modifichiamolo in modo che il puntatore punti a __malloc_hook.

Nota che __memalign_hook di solito inizia con 0x7f e zeri prima di esso, quindi è possibile falsificarlo come un valore nel fast bin 0x70. Poiché gli ultimi 4 bit dell’indirizzo sono casuali ci sono 2^4=16 possibilità perché il valore finisca puntando dove ci interessa. Quindi viene eseguito un BF attack qui in modo che il chunk finisca così: 0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23).

(Per maggiori informazioni sul resto dei byte controlla la spiegazione nel how2heap example). Se il brute force fallisce il programma semplicemente crasha (riavviare fino a quando funziona).

Poi, vengono eseguiti 2 malloc per rimuovere i 2 chunk iniziali del fast bin e viene allocato un terzo per ottenere un chunk in __malloc_hook.

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

Parte 2: Unsorted_bin attack

Per maggiori informazioni puoi consultare:

Unsorted Bin Attack

Ma fondamentalmente permette di scrivere main_arena + 0x68 in qualsiasi posizione specificata in chunk->bk. Per l’attacco scegliamo __malloc_hook. Poi, dopo averlo sovrascritto useremo una relative overwrite per puntare a un one_gadget.

Per questo iniziamo a prendere un chunk e metterlo nel 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

Nota che questo attacco corrompe l’unsorted bin (quindi anche small e large). Quindi possiamo solo use allocations from the fast bin now (un programma più complesso potrebbe fare altre allocazioni e crashare), e per attivare questo dobbiamo alloc the same size or the program will crash.

Quindi, per innescare la scrittura di main_arena + 0x68 in __malloc_hook, dopo aver impostato __malloc_hook in unsorted_bin_ptr->bk dobbiamo semplicemente eseguire: malloc(0x80)

Passo 3: Impostare __malloc_hook su system

Nel passo uno abbiamo controllato un chunk contenente __malloc_hook (nella variabile malloc_hook_chunk) e nel secondo passo siamo riusciti a scrivere lì main_arena + 0x68.

Ora, abusiamo di una partial overwrite in malloc_hook_chunk per usare l’indirizzo libc che abbiamo scritto lì (main_arena + 0x68) per puntare a un indirizzo one_gadget.

Qui è necessario bruteforce 12 bits of randomness (più info nell’how2heap example).

Infine, una volta sovrascritto l’indirizzo corretto, chiama malloc e innesca il one_gadget.

Suggerimenti moderni e varianti

  • Unsorted-bin hardening (2.28+): Le verifiche di integrità aggiuntive sugli unsorted chunks (controllo coerenza size + list linkage) rendono la classica unsorted‑bin write fragile. Per sopravvivere a _int_malloc, devi mantenere i link fd/bk consistenti e le dimensioni plausibili, il che di solito richiede primitive più potenti di una semplice partial overwrite.
  • Hook removal (2.34+): Con __malloc_hook rimosso, adatta la primitive per atterrare su qualunque GOT/global scrivibile che puoi poi riutilizzare (es., overwrite exit@GOT in non-PIE binaries) oppure pivotare a un top‑chunk hijack in stile House of Pie per controllare top invece di un hook.
  • Any‑address fastbin alloc (romanking98 writeup): La seconda parte mostra come riparare la freelist 0x71 e usare la unsorted‑bin write per far atterrare una allocazione fastbin sopra __free_hook, poi mettere system("/bin/sh") e attivarla tramite free() su libc‑2.24 (pre-hook removal).

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks