Compilando un esempio di overflow del buffer in Linux moderno?

12

Sto provando a compilare un semplice esempio di overflow del buffer su una VM i386 Debian. L'eseguibile va bene, ma EIP non viene sovrascritto correttamente nonostante venga fornito un input sufficientemente grande da sovraccaricare il buffer e sovrascrivere l'EIP spinto nello stack. Ecco i miei comandi come root:

sysctl -w kernel.randomize_va_space=0
gcc test.c -z execstack -z norelro -fno-stack-protector -D_FORTIFY_SOURCE=0 -ggdb -o test

Come puoi vedere, ho:

  • Crea lo stack eseguibile
  • Canali dello stack rimossi
  • Sistema ASLR disattivato
  • Protezioni di relro rimosse
  • Disabilita le protezioni FORTIFY_SOURCE di gcc

Ecco test.c:

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

int main(int argc, char **argv) {
  char buf[128];
  if(argc < 2) return 1;
  strcpy(buf, argv[1]);
  printf("%s\n", buf);
  return 0;
}

Ho sperimentato stringhe di crash (solo tutte As) di lunghezza da 128-256. In gdb, l'EIP spinto non viene mai sovrascritto. Realisticamente dovrebbe essere solo una stringa di 132 byte per sovrascrivere EIP in quanto non ci sono altre variabili di stack locali.

C'è qualche altra protezione che devo disabilitare durante la compilazione? O c'è qualcos'altro da disabilitare con sysctl?

    
posta B-MO 15.09.2015 - 08:41
fonte

2 risposte

4

Il tuo esempio qui segfault (o causa la chiusura del programma se la protezione dello stack è attiva).

Forse dovresti provare a spostare il buffer overflow in un'altra funzione. Forse la tua versione di gcc sta convertendo return 0; dal principale in exit(0); .

    
risposta data 15.09.2015 - 11:22
fonte
13

Mentre la risposta accettata è corretta nel suggerire di spostare tutto in una funzione diversa non spiega perché.

Come puoi vedere nelle queste domande e risposte main() funzioni spesso eseguono un allineamento dello stack per garantire che lo stack è configurato correttamente. Viene eseguita la seguente istruzione:

83 e4 f0 and esp, 0xfffffff0

Questo allineerà lo stack a 8 byte. Ciò significa che è stata eseguita un'operazione di sottrazione su esp . Pertanto, per superare l'indirizzo di ritorno è necessario 128 bytes + <variable stack alignment> + <optional saved ebp> + <new_return_address> .

Ho compilato e eseguito il tuo programma (ho dovuto aggiungere un -m32 ).

Starting program: /home/user/Private/misc/overflow_test  
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFaaaabbbbcccc
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFFFFaaaabbbbcccc

Program received signal SIGSEGV, Segmentation fault.
0x63636363 in ?? ()

Ho usato 128 come, e poi 4 di ogni nuova lettera.

Decompilando il programma vediamo le seguenti linee:

;      .//overflow_test.c:4
;-- main: 
;-- sym.main: 
0x0804842d    55             push ebp  
0x0804842e    89e5           mov ebp, esp  
0x08048430    83e4f0         and esp, 0xfffffff0 
0x08048433    81ec90000000   sub esp, 0x90 

Qui vediamo che 0x90 (144) viene sottratto dallo stack. Ciò significa che più di 128 byte di spazio sono allocati per le variabili locali. Questa risposta SO fornisce alcuni motivi per cui ciò potrebbe verificarsi. Quindi se conti i 128 byte, i 16 byte aggiuntivi aggiunti per le variabili locali e assumi 8 byte di allineamento dello stack: Poi hai EBP sovrascritto con 0x62626262 e l'indirizzo di ritorno con 0x63636363 .

Le normali funzioni generalmente non eseguono questo passo di allineamento della pila. Ecco perché quando lo hai spostato in una funzione separata, tutto ha funzionato come previsto. Nel reale sfruttamento, è altamente improbabile che le probabilità di sfruttare i parametri in main() . È più realistico l'esecuzione in un ambito di applicazione diverso.

    
risposta data 15.09.2015 - 14:16
fonte

Leggi altre domande sui tag