2012-04-11 5 views
5

Jednym z oczywistych sposobów, aby spowodować przepełnienie stosu i uzyskać Segmentation fault byłoby rekursywne przepychanie ramek stosu jeden na drugim, aż zacznie się hukać. Zastanawiam się, czy przepełnienie stosu może się zdarzyć, nawet nie przesuwając nowych klatek stosu.Jak przepełnić stos bez przesuwania nowych klatek stosu?

Utworzenie wystarczająco dużej tablicy może zrobić to również z doświadczenia, ale z innych możliwych scenariuszy?

+0

To byłoby w środowisku Linux/UNIX. –

+1

'alloca' i VLA. – Mat

Odpowiedz

3

C99 wykorzystuje zmienną tablicę rozmiarów, której można użyć i której rozmiar zostanie zmieniony na większy. Jednak ta skalowalna tablica jest implementowana za pomocą alloca. Oto przykładowy kod w UNIX ENV:

#include <stdio.h> 
#include <alloca.h> 
#include <stdlib.h> 
#include <stdbool.h> 

int 
main() 
{ 
    while (true) 
    { 
     void *p = alloca(32UL); 
     printf("new memory allocated at %p \n", p); 
    } 
    exit(EXIT_SUCCESS); 
} 

A twoje wyjście będzie wyglądać następująco

new memory allocated at 0xbf800a60 
new memory allocated at 0xbf800a30 
new memory allocated at 0xbf800a00 
new memory allocated at 0xbf8009d0 
new memory allocated at 0xbf8009a0 
[1] 3977 segmentation fault ./a.out 

alloca jest w rodzinie funkcji malloc, oprócz tego, że alokowana pamięć na stosie przez dostosowanie wskaźnik stosu.

1

nadużycie alloca() lub _alloca() jeśli rozwój na Windows SDK/VS:

Funkcja alloca() przydziela rozmiar bajtów pamięci na ramce stosu z rozmówcy.

Uwaga _alloca() jest teraz przestarzała na rzecz _malloca().

1

Zasadniczo "stos" to tylko część pamięci, a przepełnienie stosu występuje, gdy ESP/EBP wykracza poza zakres tej pamięci.

Można to zrobić na kilka sposobów:

  1. stworzyć ogromny stos przyznane tablicę, która jest większa niż wielkość pozostałej przestrzeni stosu: int x[10000000];
  2. Ustaw ESP bezpośrednio: __asm mov esp, 0x0
  3. Uszkadzaj stos, więc gdy rozwinie się obecna funkcja, ESP/EBP zostaną ustawione na śmieci: int x; memset(&x, 0, 10000000);

I coun tless inne sposoby ...

1

deklarując i stosując macierz większy niż rozmiar stosu:

$ ulimit -s 
8192 
$ 

następnie

int main(void) 
{ 
    volatile char bla[8192 * 1024 + 16] = {0}; 
} 

może wysypać podczas wykonywany.

+0

dlaczego typ lotny? –

+0

w moim przykładzie, aby uniknąć optymalizacji kompilatora, ponieważ nie jest on używany w innym miejscu w programie. Jeśli utworzysz pętlę 'for' do drukowania wszystkich elementów za pomocą' printf', nie będziesz potrzebował kwalifikatora 'volatile', ponieważ kompilator nie może go zoptymalizować. – ouah