Come funziona questo semplice buffer overflow?

3

Ho questo semplice codice

vuln.c

#include <stdio.h>
#include <string.h>

int main(int argc, char** argv)
{
    char buffer[500];
    strcpy(buffer, argv[1]);
    printf("%s", buffer);
    return 0;
}

Sto tentando di eseguire un buffer overflow e

  • Riempi il buffer con un codice dannoso
  • Modifica l'indirizzo di ritorno per reindirizzare il codice dannoso

Idealmente, credo che quando sovrascrivo il mio buffer da 500, successivamente sovrascriverò il puntatore di base, seguito dall'indirizzo di ritorno.

Ecco come ho provato a sovrascrivere il buffer

gcc vuln.c
./a.out $(python -c 'print "\x41" * 501')

Dato che sto mettendo 501 "A" nel buffer, dovrebbe overflow teoricamente, giusto? Ma questo non sta succedendo. Non ottengo un errore di segmentazione, invece, ottengo l'output di "AAAA .." e il programma esce normalmente. (Non ho contato il numero di As ..).

Quindi ho attivato GDB e ho iniziato a giocare con il numero di As finché I do non ha riscontrato un errore di segmentazione. E trovo che ottengo un errore di segmentazione quando inserisco 520 "A"! Come?

Con 520 A's, GDB's info registers mi dà

Econ521A,conlostessocomandoGDB,ottengo

Come puoi vedere, nell'immagine 1, il punto base viene riempito con \ x41 (esadecimale per A) e nell'immagine 2, il BP è riempito con \ x41s e anche l'IP inizia a essere riempito.

Non lo capisco. Quindi la mia domanda è: perché 520? E perché non ha overflow su 501?

    
posta Izy- 08.11.2018 - 12:31
fonte

1 risposta

4

Ciò è dovuto ad un allineamento a 16 byte, che i compilatori fanno su x86 (_64) per la compatibilità con le istruzioni SIMD che operare su 128 bit (16 byte). A causa di ciò c'è un "padding" tra il buffer e i registri salvati, 12 byte nel tuo caso.

Tecnicamente, il buffer viene già sovrascritto se si superano i 500 caratteri A del programma perché la stringa è terminata con null. Ma quel byte zero sovrascrive solo il primo dei byte del padding. Tra questi byte di riempimento e il rip salvato c'è anche il rbp salvato (8 byte). Quindi il layout è fondamentalmente come questo (se canarini sono in uso - -fstack-protector - allora il valore delle canarie è posto tra padding e registri salvati):

buffer [500 bytes] | padding [12 bytes] | saved rbp [8 bytes] | saved rip [8 bytes]

Quindi con 520 A caratteri si sovrascrive prima il padding e il% co_de salvato prima che il primo byte del rbp salvato venga sovrascritto con un byte zero.

    
risposta data 08.11.2018 - 15:13
fonte

Leggi altre domande sui tag