2013-03-12 8 views
11

Sto provando a prendere il controllo su un overflow dello stack. In primo luogo, ecco un esempio di codice C ho compilato su un x32 VM Linux (gcc -fno-stack-protector -ggdb -o first first.c),L'overflow del buffer è apparso prima del previsto

#include "stdio.h" 

int CanNeverExecute() 
{ 
    printf("I can never execute\n"); 
    return(0); 
} 

void GetInput() 
{ 
    char buffer[8]; 

    gets(buffer); 
    puts(buffer); 
} 

int main() 
{ 
    GetInput(); 
    return(0); 
} 

Poi debugger (sapore Intel): dump del codice assembler per la funzione GetInput:

0x08048455 <+0>: push ebp 
0x08048456 <+1>: mov ebp,esp 
0x08048458 <+3>: sub esp,0x28 
0x0804845b <+6>: lea eax,[ebp-0x10] 

Qui possiamo vedere che sub esp, 0x28 riserva 40 byte per una variabile buffer (Right?). La funzione CanNeverExecute si trova all'indirizzo 0x0804843c. Quindi, per eseguire la funzione CanNeverExecute, ho bisogno di mettere 40 byte nella variabile del buffer, quindi passa 8 byte per il puntatore di base memorizzato e quindi 8 byte del puntatore di ritorno che voglio cambiare.

Quindi, ho bisogno di una stringa di 48 simboli ASCII più \x3c\x84\x04\x08 alla fine (indirizzo della funzione CanNeverExecute). Questo è in teoria. Ma in pratica ho bisogno di soli 20 byte prima di indirizzo del puntatore di ritorno:

~/hacktest $ printf "123456789\x3c\x84\x04\x08" | ./first 
123456789.. 
I can never execute 
Illegal instruction (core dumped) 

Perché ha bisogno solo 20 byte invece di 48? Dov'è il mio errore?

risposta

2

se si prende parte più grande dello smontaggio si vedrà:

08048445 <GetInput>: 
8048445: 55      push %ebp 
8048446: 89 e5     mov %esp,%ebp 
8048448: 83 ec 28    sub $0x28,%esp 
804844b: 8d 45 f0    lea -0x10(%ebp),%eax 
804844e: 89 04 24    mov %eax,(%esp) 
8048451: e8 9a fe ff ff   call 80482f0 <[email protected]> 
8048456: 8d 45 f0    lea -0x10(%ebp),%eax 
8048459: 89 04 24    mov %eax,(%esp) 
804845c: e8 9f fe ff ff   call 8048300 <[email protected]> 
8048461: c9      leave 
8048462: c3      ret 

EBP viene salvato, esp viene spostato EBP, allora 40 è sottratto da esp (stack frame, come hai scritto), ma puntatore il buffer viene passato a get tramite il registro eax e eax viene caricato con ebp-0x10!

lea -0x10(%ebp),%eax 

quindi è necessario solo 20 byte di overflow del buffer (16 riservati + 4 per puntatore base memorizzati sul sistema a 32-bit)

9

Prima di tutto, l'assembly è a 32 bit. EBP salvato e indirizzo di ritorno sono 4 byte ciascuno.

In secondo luogo, la variabile buffer non inizia nello stack top (ESP) - inizia da ebp-0x10. Che è 20 byte di distanza dall'indirizzo di ritorno. 0x10 è 16 byte, quindi 4 in più per l'EBP salvato.