Perché JMP ESP invece di saltare direttamente nello stack

6

In primo luogo, mi dispiace se questo post non si adatta esattamente qui, o potrebbe essere migliore in RE. Potremmo spostarlo se necessario.

Quindi stavo leggendo questo writeup su un exploit in vulnserver (per coloro che non lo so, vulnserver è un programma progettato pensando a difetti, questo è, per praticare tecniche di sfruttamento)

A un certo punto, dice:

In this step we have to check the registers and the stack. We have to find a way to jump to our buffer to execute our code. ESP points to the beginning of the C part of our buffer. We have to find a JMP ESP or CALL ESP instruction. Do not forget, that the address must not contain bad characters!

Questo ha senso, ma; Non sarebbe possibile e più facile saltare direttamente nello stack dal momento che controlliamo EIP? (Assumiamo che ASLR e DEP siano disabilitati, ovviamente). Principalmente perché:

  1. Come fa a sapere che ESP punta al suo codice shell? Perché ESP punta esattamente lì? Non dovrebbe invece puntare alla fine del suo shellcode?

  2. In che modo dovrebbe funzionare il riavvio o in computer diversi?

Grazie.

    
posta Pedro Javier Fernández 16.04.2017 - 17:11
fonte

2 risposte

6

Il tuo payload exploit finisce sullo stack perché stai sovraccaricando un buffer nello stack, e in questo modo ottieni anche il controllo dell'indirizzo di ritorno.

L'ESP punta direttamente all'inizio del tuo payload (dopo l'esecuzione di ret nella funzione che stai attaccando) perché metti il payload subito dopo i 4 byte che sovrascrivono l'indirizzo di ritorno nello stack. ret apre 4 (o 8) byte in EIP, lasciando ESP che punta al payload che segue direttamente.

Ma non sai quale valore ESP avrà a quel punto , a causa dello stack ASLR e perché una diversa profondità dello stack di chiamate che porta fino a questo punto potrebbe cambiare l'indirizzo. Quindi non puoi codificare un indirizzo di ritorno corretto .

Ma se ci sono byte che decodificano come jmp esp o call esp ovunque su un indirizzo fisso (non ASLR) nella memoria del processo , puoi specificare che indirizzo come indirizzo di ritorno nel tuo exploit. L'esecuzione andrà lì, quindi al tuo payload.

Questo è spesso il caso: alcune DLL non hanno ASLR abilitato per il loro codice e il codice dell'eseguibile principale potrebbe non essere ASLR.

Codice ASLR per il codice tutto che sconfigge un attacco jmp esp , a meno che l'autore dell'attacco non possa far filtrare gli indirizzi nel processo di destinazione.

Si noti che per codice a 64 bit è improbabile che si possa utilizzare jmp rsp per overflow del buffer basato su stringhe, perché gli indirizzi di codice conterranno alcuni 0 di byte iniziali .

Quindi, jmp esp ti offre un exploit molto più affidabile di quello che indovina ripetutamente un indirizzo di ritorno (con una slitta NOP molto grande).

L'ipotesi ripetuta bloccherà il processo di destinazione ogni volta che sbagli, ma un jmp esp può darti un'alta probabilità di successo al primo tentativo. Ciò eviterà di lasciare i registri di crash. Potrebbe anche sconfiggere un sistema di rilevamento delle intrusioni che cerca di bloccare i processi del server e blocca le connessioni dal tuo indirizzo IP o simili.

Si noti che l'istruzione a 2 byte che si sta cercando può apparire come parte di un'altra istruzione quando il programma viene eseguito normalmente o come dati statici (in particolare i dati di sola lettura sono spesso in pagine eseguibili). Quindi devi solo cercare la sequenza da 2 byte, non per jmp esp nello smontaggio del programma. I compilatori non useranno mai jmp esp , quindi non ne troverai uno in questo modo.

Più in generale , qualsiasi funzione che termina con un puntatore del buffer in qualsiasi registro (ad esempio da memcpy o soprattutto strcpy ) può consentire un attacco ret2reg , cercando un'istruzione jmp eax .

Questo può funzionare in modalità 64 bit, dove gli indirizzi hanno alcuni byte zero alti; se lo zero finale di strcpy scrive quel byte di indirizzo elevato per te, la fine della stringa di exploit potrebbe essere il byte dell'indirizzo diverso da zero che sovrascrive l'indirizzo di ritorno nello stack.

In questo caso, il payload dell'eseguibile andrebbe prima dell'indirizzo di ritorno, nel punto del buffer in cui la funzione lascia un registro che punta. (Tipicamente l'inizio del buffer se ci sono dei puntatori utili al buffer nei registri)

    
risposta data 10.03.2018 - 04:31
fonte
4

Dopo che un buffer ha superato il limite, ESP ha lo shellcode. Potresti verificarlo in immunità, EIP deve indicare ESP. La mia comprensione è prima che l'exploit, le DLL di sistema, dovrebbero utilizzare ESP, a seconda di quando vengono chiamate le DLL.

Ma dopo che il buffer è stato traboccato, EIP non ha idea di dove puntare. Nota che i 4 byte che passiamo a EIP possono essere uno qualsiasi degli indirizzi [jmp ESP].

Quindi va così -

  1. Overflow del buffer esattamente fino a EIP
  2. Passa l'indirizzo [jmp ESP] a EIP
  3. Il valore memorizzato in ESP viene eseguito (NOPs + Shellcode)

Ho scritto un exploit e ho usato variazioni di indirizzo a [jmp ESP] e ogni volta che potevo sfruttare la vulnerabilità.

Ecco l'exploit.py, nota che sto usando la dcr RPCRT. Ma possiamo usare shell32.dll e altre DLL di sistema pure.

link

Sto usando shellcode con shell shell con alcuni NOP aggiuntivi.

BTW if the OS has some kind of protections or the compiler has added some protections while compiling the original src code. This'll become a treasure hunt to find the location of the shellcode. We'll then need to use several jumps to get to the shellcode.

Spero che ti aiuti!

    
risposta data 31.05.2017 - 14:00
fonte

Leggi altre domande sui tag