First Fit

Impara e pratica l'Hacking su AWS: HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica l'Hacking su GCP: HackTricks Training GCP Red Team Expert (GRTE)

Sostieni HackTricks

First Fit

Quando liberi la memoria in un programma che utilizza glibc, vengono utilizzati diversi "bin" per gestire i blocchi di memoria. Ecco una spiegazione semplificata di due scenari comuni: unsorted bins e fastbins.

Unsorted Bins

Quando liberi un blocco di memoria che non è un blocco veloce, va al bin non ordinato. Questo bin funziona come una lista in cui i nuovi blocchi liberati vengono aggiunti all'inizio (la "testa"). Quando richiedi un nuovo blocco di memoria, l'allocatore guarda il bin non ordinato dalla fine (la "coda") per trovare un blocco abbastanza grande. Se un blocco dal bin non ordinato è più grande di quanto necessiti, viene diviso, con la parte anteriore restituita e la parte rimanente che rimane nel bin.

Esempio:

  • Alloci 300 byte (a), poi 250 byte (b), liberi a e richiedi di nuovo 250 byte (c).

  • Quando liberi a, va al bin non ordinato.

  • Se successivamente richiedi di nuovo 250 byte, l'allocatore trova a in coda e lo divide, restituendo la parte che soddisfa la tua richiesta e mantenendo il resto nel bin.

  • c punterà al precedente a e sarà riempito con i dati di a.

char *a = malloc(300);
char *b = malloc(250);
free(a);
char *c = malloc(250);

Fastbins

I fastbins sono utilizzati per piccoli blocchi di memoria. A differenza dei blocchi non ordinati, i fastbins aggiungono nuovi blocchi all'inizio, creando un comportamento di tipo last-in-first-out (LIFO). Se richiedi un piccolo blocco di memoria, l'allocatore preleverà dalla testa del fastbin.

Esempio:

  • Alloci quattro blocchi da 20 byte ciascuno (a, b, c, d).

  • Quando li liberi in qualsiasi ordine, i blocchi liberati vengono aggiunti alla testa del fastbin.

  • Se successivamente richiedi un blocco da 20 byte, l'allocatore restituirà il blocco liberato più di recente dalla testa del fastbin.

char *a = malloc(20);
char *b = malloc(20);
char *c = malloc(20);
char *d = malloc(20);
free(a);
free(b);
free(c);
free(d);
a = malloc(20);   // d
b = malloc(20);   // c
c = malloc(20);   // b
d = malloc(20);   // a

Altri riferimenti ed esempi

  • ARM64. Uso dopo la liberazione: Generare un oggetto utente, liberarlo, generare un oggetto che ottiene il chunk liberato e consente di scriverci sopra, sovrascrivendo la posizione di user->password da quello precedente. Riutilizzare l'utente per bypassare il controllo della password

  • Il programma consente di creare note. Una nota avrà le informazioni della nota in un malloc(8) (con un puntatore a una funzione che potrebbe essere chiamata) e un puntatore a un altro malloc(<size>) con il contenuto della nota.

  • L'attacco consisterebbe nel creare 2 note (nota0 e nota1) con contenuti malloc più grandi della dimensione delle informazioni della nota e quindi liberarle in modo che entrino nel fast bin (o tcache).

  • Successivamente, creare un'altra nota (nota2) con dimensione del contenuto 8. Il contenuto sarà nella nota1 poiché il chunk verrà riutilizzato, dove potremmo modificare il puntatore della funzione per puntare alla funzione win e quindi Usare-Dopo-Liberazione la nota1 per chiamare il nuovo puntatore della funzione.

  • È possibile allocare della memoria, scrivere il valore desiderato, liberarla, reallocarla e poiché i dati precedenti sono ancora lì, verranno trattati secondo la nuova struttura prevista nel chunk, rendendo possibile impostare il valore o ottenere la flag.

  • In questo caso è necessario scrivere 4 all'interno di un chunk specifico che è il primo ad essere allocato (anche dopo averli liberati forzatamente tutti). Su ciascun nuovo chunk allocato viene memorizzato il suo numero nell'indice dell'array. Quindi, allocare 4 chunk (+ quello inizialmente allocato), l'ultimo avrà 4 al suo interno, liberarli e forzare la riallocazione del primo, che utilizzerà l'ultimo chunk liberato che è quello con 4 al suo interno.

Last updated