2013-03-12 6 views
11

Ich versuche, eine Kontrolle über einen Stapelüberlauf zu nehmen. Als erstes ist hier ein Beispiel für C-Code I auf einem x32 kompiliert VM Linux (gcc -fno-stack-protector -ggdb -o first first.c),Pufferüberlauf erschien, bevor es erwartet wird

#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); 
} 

Dann Debugger (intel Geschmack): dump von Assembler-Code für die Funktion GetInput:

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

Hier Wir können sehen, dass sub esp, 0x28 40 Bytes für eine Puffervariable reserviert (Right?). CanNeverExecute Funktion befindet sich in Adresse 0x0804843c. Also, um CanNeverExecute Funktion ausführen, muss ich 40 Bytes in die Puffervariable setzen, dann geht 8 Bytes für den gespeicherten Basiszeiger und dann 8 Bytes des Rückkehrzeigers ich möchte ändern.

Also brauche ich am Ende eine Reihe von 48 ASCII-Symbolen plus \x3c\x84\x04\x08 (Adresse der CanNeverExecute Funktion). Das ist in der Theorie. Aber in der Praxis muss ich nur 20 Bytes vor Adresse des Schleppzeiger:

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

Warum braucht es nur 20 Bytes statt 48? Wo ist mein Fehler?

Antwort

2

Wenn Sie größere nehmen Teil Zerlegen Sie werden sehen:

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 gespeichert wird, besonders auf EBP bewegt, dann wird 40 von esp subtrahiert (Stack-Frame, wie Sie geschrieben haben), aber Zeiger zu puffern wird an gets über eax register übergeben, und eax wird mit ebp-0x10 geladen!

lea -0x10(%ebp),%eax 

Sie müssen also nur 20 Bytes der Pufferüberlauf (16 + 4 reserviert für gespeicherte Basiszeiger auf 32-Bit-System)

9

Zunächst einmal ist Ihre Baugruppe 32-Bit. Gespeicherte EBP und Rückkehradresse sind jeweils 4 Bytes.

Zweitens startet die buffer Variable nicht am Stack-Top (ESP) - es beginnt bei ebp-0x10. Das ist 20 Bytes von der Absenderadresse entfernt. 0x10 ist 16 Bytes, dann 4 mehr für das gespeicherte EBP.