2016-02-03 47 views
5

Oto kawałek kodu:Zamówienie zmiennej deklaracji w asm x86?

int main() 
{ 

    char buffer[64]; 
    int check; 
... 

Jak widać, check deklaruje PObuffer, więc w stosie, musimy mieć checkPOWYŻEJbuffer w stosie prawej?

Jednak, kiedy demontażu (x86) to z gdb, to co mam:

->check w 0xbffff4f8

->buffer na 0xbffff4b8

moje pytanie: czy istnieje konkretna kolejność w stosie dla zmiennej lokalnej?

Muszę też powiedzieć, że wypróbowałem to samo na innym komputerze (również x86, takie same opcje kompilacji gcc, ale inna wersja gdb i dystrybucja linuxa), a kolejność nie jest taka sama ...: S

Dzięki!

PS: jeśli chcesz więcej szczegółów, zobacz zrzut ekranu: (lewy z komputera 1 i prawo z komputera 2) enter image description here

+13

Nie, kompilator nie musi przechowywać ich w określonej kolejności. Zmienne mogą wcale nie być w pamięci, jeśli mieszczą się w rejestrach lub są całkowicie zoptymalizowane. – Jester

+2

Zmienne mogą mieć dowolną kolejność i może być dowolna liczba bajtów dopełnienia przed, po lub między zmiennymi. – user3386109

+2

Dla zachowania przejrzystości, bajty dopełnienia służą do zachowania wyrównania. –

Odpowiedz

2

Jest -fstack-protect w gcc, aby zmienić kolejność zmiennych stosu, domyślnie włączona w jakiś Linux Wersja systemu operacyjnego od prawie 10 lat, szczególnie Ubuntu, Redhat, gentoo. domyślnie również od gcc 4.8.3 ("4.9, a później włączyć -fstack-protector-silny.")

Ubuntu strona o gcc domyślne: https://wiki.ubuntu.com/ToolChain/CompilerFlags

Ubuntu specyficznych flag domyślny kompilator toolchain używane, aby pomóc zapewnić dodatkowe funkcje bezpieczeństwa do Ubuntu. ... Domyślne flagi -fstack-protector ... Pierwsza włączona w systemie Ubuntu 6.10.

Ubuntu strona o ochronie stosu https://wiki.ubuntu.com/GccSsp

gcc 4.1 pochodzi z SSP teraz, co jest miłym technologii w celu zmniejszenia możliwości wykorzystania wielu przepełnienia bufora. ... SSP dostarcza technologię, aby zatrzymać Exploitability tej klasy luki (1) zamianom zmienne stos ... RedHat i Gentoo używają SSP domyślnie lat

Ta zmiana kolejności wymaga kilku O(n^2) spacery wszystkie lokalne zmienne funkcji, które spowodują spowolnienie kompilacji dla długich funkcji, na przykład "Dlaczego skompilowanie ponad 100 000 linii std :: vector :: push_back zajmuje dużo czasu?" - https://stackoverflow.com/a/14034393/196561

odroczony alokacja jest zmuszony gdy -fstack-protect jest włączona (czasami musi uporządkować wszystkie zmienne stosu). ..cfgexpand.c

969 /* A subroutine of expand_one_var. VAR is a variable that will be 
970 allocated to the local stack frame. Return true if we wish to 
971 add VAR to STACK_VARS so that it will be coalesced with other 
972 variables. Return false to allocate VAR immediately. 
973 
974 This function is used to reduce the number of variables considered 
975 for coalescing, which reduces the size of the quadratic problem. */ 
976 
977 static bool 
978 defer_stack_allocation (tree var, bool toplevel) 
980 /* If stack protection is enabled, *all* stack variables must be deferred, 
981  so that we can re-order the strings to the top of the frame. */ 

Więc, gcc będzie uporządkować wszystkie zmienne stosu i ciągi będzie w górnej części ramki. Wypróbuj opcję -fno-stack-protector, aby wyłączyć.

Jak zwykle autor gcc nie dokumentują jak -fstack-protect prace w dokumentacji publicznej https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html:

-fstack-protector Emit dodatkowego kodu w celu sprawdzenia przepełnienia bufora, takich jak ataki stosu rozbijając. Odbywa się to poprzez dodanie zmiennej strażnika do funkcji z obiektami wrażliwymi. Obejmuje to funkcje, które wywołują alloca i działa z buforami większymi niż 8 bajtów. Osłony są inicjowane po wprowadzeniu funkcji, a następnie sprawdzane po jej wyjściu. Jeśli kontrola wartownika nie powiedzie się, zostanie wydrukowany komunikat o błędzie i program zostanie zamknięty.

-fstack-protector-all Podobnie jak -fstack-protector oprócz tego, że wszystkie funkcje są chronione.

Podobnie jak -fstack-protector, ale zawiera dodatkowe funkcje, które mają być chronione - te, które mają lokalne definicje tablicowe lub zawierają odniesienia do lokalnych adresów ramek.

-fstack-protector-explicit Podobnie jak -fstack-protector, ale chroni tylko te funkcje, które mają atrybut stack_protect.

A jedyna dokumentacja tablicy wcześniej nie mieszkańców widzę jest prawdziwe, najlepiej dokumentacja: kod źródłowy

https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_6-branch/gcc/cfgexpand.c?revision=175029&view=markup#l1526 - expand_used_vars()

1533   if (has_protected_decls) 
1534   { 
1535    /* Phase 1 contains only character arrays. */ 
1536    expand_stack_vars (stack_protect_decl_phase_1); 
1537  
1538    /* Phase 2 contains other kinds of arrays. */ 
1539    if (flag_stack_protect == 2) 
1540    expand_stack_vars (stack_protect_decl_phase_2); 
1541   } 
1542  
1543   expand_stack_vars (NULL); 

faza 1 i faza 2 Vars są oddzielone stack_protect_decl_phase()https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_6-branch/gcc/cfgexpand.c?revision=175029&view=markup#l1235

1235 /* Return nonzero if DECL should be segregated into the "vulnerable" upper 
1236  part of the local stack frame. Remember if we ever return nonzero for 
1237  any variable in this function. The return value is the phase number in 
1238  which the variable should be allocated. */ 
1239  
1240 static int 
1241 stack_protect_decl_phase (tree decl) 
... 
1243  unsigned int bits = stack_protect_classify_type (TREE_TYPE (decl)); 
... 
1249  if (flag_stack_protect == 2) 
1250  { 
1251   if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY)) 
1252    && !(bits & SPCT_HAS_AGGREGATE)) 
1253   ret = 1; 
1254   else if (bits & SPCT_HAS_ARRAY) 
1255   ret = 2; 
1256  } 

stack_protect_classify_type zwróci bity HAS_ARRAY z HAS_*_CHAR_ARRAY tylko dla tablic znaków (zarówno char, unsigned char and signed char)

+0

Dzięki, potrzebuję trochę czasu, aby zrozumieć wszystko w twojej odpowiedzi. Pomyślałem, że '-fstack-protect' dotyczy tylko dodawania kanarka do stosu, aby zapobiec przepełnieniu stosu poprzez sprawdzenie, czy ten kanarek został nadpisany. Czy możesz potwierdzić, że z '-fno-stack-protector' kolejność zmiennej zadeklarowanej na stosie jest zgodna z porządkiem deklaracji w pliku źródłowym? –

+0

'-fstack-protector' /' -fno-stack-protector' może (i będzie) zmieniać kolejność zmiennych na stosie. Masz test, po prostu skompiluj go z '-fno-stack-protector' i sprawdź kolejność. Jeśli moja odpowiedź rozwiąże Twój problem, możesz go zaakceptować, klikając przycisk "Odblokuj" w kształcie litery "v" lub możesz poczekać na inne odpowiedzi. – osgx

+0

Ok. Więc jeśli dobrze rozumiem, kolejność zmiennych na stosie może się zmienić, nawet jeśli ustawimy '-fno-stack-protection' right? Nie mogę tego sprawdzić w tej chwili, ale tak szybko, jak to możliwe. Dzięki –