2013-03-19 10 views
15

Czy inteligentnie przypisuje się pamięć do algorytmu gcc, aby zapobiec atakowi przepełnienia bufora?Problem z przydziałem pamięci gcc - atak przepełnienia buforu

int function(char *str) { 
    int a = 0;     // See the 
    char b[16] = "abcd";  // changes here 

    if(!strcmp(b, str)) 
     a = 1; 

    return a; 
} 

i

int function(char *str) { 
    char b[16] = "abcd";  // See the 
    int a = 0;     // changes here 

    if(!strcmp(b, str)) 
     a = 1; 

    return a; 
} 

Kiedy debugowanie z gdb, zawsze alokacji pamięci, pierwszą liczbę całkowitą zmiennych, a następnie układ znaków; bez względu na kolejność deklaracji zmiennych. tj. W powyższych przypadkach kompilator przydziela pamięć najpierw do a, a następnie do b.

(higher address) 
    Memory 
|  | 
|  | 
+--------+ 
|  | 
|  | 
|  | 
|  | 
+--------+ <----- b (16 bytes) 
|  | 
+--------+ <----- a (4 bytes) 
|  | 
(lower address) 

Tak więc, nawet jeśli będziemy dostarczać więcej niż 16 znaków w str, nie może wpływać na wartość a. Czy ktoś może mi tutaj pomóc?

Dziękuję.

+1

_Standard_ umożliwia takie porządkowanie w dowolnych celach, które chce wykonać kompilator. Najczęściej - optymalizacja. To wciąż "inteligencja", ale nie do zapobiegania "atakowi przepełnienia bufora". I nadal jest niezdefiniowanym zachowaniem_ (przepełnienie bufora) –

Odpowiedz

11

Tak, jeśli jest uruchomiony z flagą -fstack-protector.

Po uruchomieniu z flagą, GCC dodaje kanarki stosowe, sortuje zmienne tablicowe do najwyższej części ramki stosu, aby utrudnić przepełnienie ich i uszkodzić inne zmienne oraz tworzy kopie argumentów funkcji, które mają być przechowywane z inni mieszkańcy.

Zobacz Wikipedia page on Buffer overflow protection i główną ProPolice więcej informacji

+0

@Ravi: Niektóre dystrybucje włączają ją domyślnie. Spróbuj skompilować z '-fno-stack-protector' i sprawdź, czy to robi różnicę. – Hasturkun

+0

@MM .: Dodano. Została w większości pominięta dla zwięzłości. – Hasturkun

+1

Masz rację. GCC domyślnie to włącz. Jeśli kompilujemy z '-fno-stack-protector', to alokujemy pamięć sekwencyjnie w kolejności deklaracji, a nie _array zmiennych do najwyższej części stosu frame_. Dziękuję Ci – Ravi

-1

Czy gcc inteligentnie przypisuje alokację pamięci, aby zapobiec atakowi przepełnienia bufora?

Nie, nie ma. Nie można zapobiec atakowi lub przepełnieniu bufora bez sprawdzania granic, co nie zawsze jest możliwe. Czasami możesz wykryć przepełnienie po fakcie.

Co najwyżej kompilator może zawierać dodatkowe informacje (tak zwane canary value) w pobliżu adresu zwrotnego na stosie i przed powrotem z funkcji sprawdzić, czy jest nienaruszone i nie jest nadpisany w wyniku przepełnienia bufora.

+2

To jest złe, GCC może zmieniać kolejność zmiennych i zapobiegać efektom przepełnienia bufora. – Hasturkun

+0

@Hasturkun Nie można zapobiec przepełnieniu bez sprawdzania granic. Czasem można go wykryć. –

+0

To prawda. Ale możesz je złagodzić, tak jak zrobiła to ProPolice, itp. – Hasturkun

2

Nawet jeśli GCC ma taką funkcję, w celu ochrony przed przepełnieniem bufora, istnieje wiele innych tu rozważania, które mogą spowodować stałą zmienną kolejność zgłoszenia. Jeśli deklaracja nie jest istotna, kompilator podejmie decyzję o alokacji w oparciu o czas i sposób użycia zmiennej w środowisku wykonawczym.

Co najważniejsze, kompilator ma nadzieję, że przydzieli zmienne w ramce stosu mając na uwadze najlepsze możliwe wyrównanie. Można to zrobić na różne sposoby w zależności od procesora i ustawienia optymalizacji. Optymalizacja prędkości może dać zupełnie inną alokację, w porównaniu do optymalizacji pod kątem zużycia pamięci. Najprawdopodobniej wprowadzi kilka zmiennych do rejestrów procesora, usuwając potrzebę alokacji pamięci RAM.

Aby odpowiedzieć na pytanie: GCC przydziela zmienne na różne sposoby, w zależności od portu kompilatora. Jak to działa, nie jest czymś, za czym programista musi nadmiernie się martwić. Mogą istnieć opcje zmiany stosu w celu ochrony przed atakami przepełnienia bufora, ale ma to sens tylko w niektórych typach aplikacji. Nie może być żadnego wejścia do konkretnego systemu, z tego, co wiemy. Dlatego nie ma sensu, aby kompilator miał domyślnie włączoną tę funkcję zabezpieczeń.

Powiązane problemy