Nie wiem czy pomoże Tobie coś co napisze marny student I roku informatyki, ale niech spróbuję:
Zaczynamy tutaj:
Kod: Zaznacz cały
0x08048437 <check_authentication+3>: sub esp,0x28
Oto coś dziwnego - program rezerwuje na stosie 0x28 bajtów (40 decymalnie) zamiast dwudziestu (16 znaków plus czterobajtowy int). To już daje do myślenia czemu tak wiele. Jedźmy dalej...
Kod: Zaznacz cały
0x0804843a <check_authentication+6>: mov eax,DWORD PTR [ebp+0x8]
0x0804843d <check_authentication+9>: mov DWORD PTR [ebp-0x24],eax
EBP+0x8 wskazuje na adres gdzie zaczyna się Twój ciąg znaków o nazwie *pass, czyli argument tej funkcji. Już jest dziwnie, że ten argument jest kopiowany na stos oddalony od EBP o 36 bajtów. Na tym nie poprzestajemy:
Kod: Zaznacz cały
0x08048440 <check_authentication+12>: mov eax,gs:0x14
0x08048446 <check_authentication+18>: mov DWORD PTR [ebp-0x4],eax
Tej linii w ogóle nie rozumiem przez to: gs:0x14. Do zmiennej lokalnej wpisywana jest pewnie jakaś stała związana z Twoją funkcją (tak myślę). Lokacja EBP-0x4 to de facto pierwsza zmienna na stosie. Następnie:
Kod: Zaznacz cały
0x0804844b <check_authentication+23>: mov DWORD PTR [ebp-0x18],0x0
Dopiero tutaj w lokacji EBP-0x18 wpisywane jest 0 czyli to musi być zmienna "flag". Zauważ, że jest oddalona aż o 24 bajty od EBP...
Kod: Zaznacz cały
0x08048452 <check_authentication+30>: mov edx,DWORD PTR [ebp-0x4]
0x08048455 <check_authentication+33>: xor edx,DWORD PTR gs:0x14
To jest dopiero dziwadło ! Do rejestru EDX ładujemy zmienną spod EBP-0x4 (ta w której było coś z gs:0x14) i co robimy ? Xorujemy EDX z gs:0x14. Jeśli wychodzi 0 (czyli zmienna z EBP-0x4 równa się GS:0x14) to wyjdź z funkcji, jeśli nie to wywołaj __stack_chk_fail@plt. Co to jest ta ostatnia funkcja zaraz powiem. Pomyślmy, na pierwszy rzut oka kod jest bez sensu, pobieramy zmienną z pamięci ładujemy na stos a potem xorujemy jej kopie z stosu z oryginałem i jeśli są takie same to zakończ funkcje a jak nie to wywołaj coś co ma "fail" w nazwie. To daje do myślenia, mianowicie myliłem się. GS:0x14 nie jest Twoim tworem od szyfrowania czy czegokolwiek

To musi być jakaś zmienna w stylu "stack protector", nie chce mi się domyślać jak ona działa ale pewnie tak że jeśli ją jakiś "cwaniaczek" zamarze pewną wartością to trzeba wywołać funkcję od tzw stack-smashingu. Pewnie samo __stack_chk_fail@plt ma coś wspólnego z fajnym napisem "*** stack smashing detected ***: ./blablabla terminated".
Rzućmy okiem na nasz stos jak są poukładane dane :
EBP - 0x4 - czterobajtowy protector
EBP - 0x18 - czterobajtowa zmienna flag, wyzerowana
EBP - 0x24 - wskaźnik na char *pass
Widać że w tym 40-bajtowym bloku są puste luki. Narysowałem sobie ładnie jak to jest rozłożone i widzę że tylko od EBP-0x14 jest miejsce na 16 bajtowy bufor. Twój kod nie inicjalizuje bufora zatem nie ma nigdzie w Asemblerze rozkazów wypełniających go czymś. Stąd brak odwołań do EBP-0x14

Nie wiem po co jest ta reszta pustych luk, albo po co jest EBP-0x28, co kryje się w dwunastobajtowym bloku od EBP-0x23 (lepiej, co dopiero będzie tam się kryć) ?
Szperałem w sieci na temat ten dziwnej funkcji __stack_chk_fail@plt i znalazłem takie coś:
http://forum.smashthestack.org/viewtopic.php?pid=1000
Szczegołnie ciekawy jest fragment:
Kod: Zaznacz cały
1. Reorders local variables so that buffers are placed after pointers
2. Copies pointers in function arguments to an area before local buffers
3. omits instrumentation code from functions to reduce overhead
4. adds a call to __stack_chk_fail() in the epilog
1. Wskaźnik powinien być przed buforem (wględem adresu bufora i wskaźnika, mam na myśli adres wskaźnika mniejszy niż adres początku bufora) gdyż jeśli damy do bufora więcej danych niż on jest w stanie pomieścić to nadpiszemy zmienne powyżej niego, czyli jeśli nasz bufor zaczyna się od EBP-0x14 to możemy nadpisać tego właśnie strażnika stosu. Wskaźnik na argument jest bezpieczny, gdyż nie da się go nadpisać (nie zapisujemy do pamięci wstecz). Jeśli coś naruszymy to naruszymy właśnie protectora a ten zaś potem jest sprawdzany czy jest taki sam jak oryginał. Zatem wszystko jest ok

2. Tak, właśnie znaleźliśmy kopiowanie wskaźnika do argumentu funkcji.
3. Nie wiem, nie zauważyłem tego w Twoim kodzie

4. Tak, jest to wywołanie.
Wychodzi na to, że jeśli dasz flage -fno-stack-protector do kompilatora to stos będzie wyglądał klasycznie. To tyle jeśli chodzi o mnie, nie czytałem nic wcześniej w necie. Nie rozgryzłem Twojego programu a potem pisałem posta. Nie, to wyglądało inaczej - na bierząco co wymyśliłem od razu tutaj pisałem zatem jest to robota wykonana w locie i gdzieś mogłem się machnąć. Przeczytaj sobie tę stronkę co podałem, ja czytałem tylko pierwsze górne linijki
