SlideShare ist ein Scribd-Unternehmen logo
1 von 40
Downloaden Sie, um offline zu lesen
Hacking. Sztuka
                           penetracji. Wydanie II
                           Autor: Jon Erickson
                           T³umaczenie: Marcin Rogó¿
                           ISBN: 978-83-246-1802-6
                           Tytu³ orygina³u: Hacking:
                           The Art of Exploitation, 2nd Edition
                           Format: 170x230, stron: 520



                                                        Zdob¹dŸ wiedzê godn¹ hakera!
                               • Co trzeba wiedzieæ, aby byæ hakerem?
                               • Jak ³amaæ has³a?
                               • Jak uzyskaæ dostêp do zabezpieczonej sieci bezprzewodowej?
                           S³owo haker kojarzy nam siê z komputerowym mistrzem manipulacji Kevinem
                           Mitnickiem. Pojêcie to jednak ewoluowa³o od czasu jego spektakularnych akcji. Zatem
                           kim jest dziœ haker? Wbrew obiegowej opinii, wiêkszoœæ hakerów nie wykorzystuje swej
                           wiedzy do niecnych celów. Dziêki swej wiedzy i dociekliwoœci przyczyniaj¹ siê do
                           rozwoju bezpieczeñstwa sieci i programów. Nikt bowiem nie potrafi tak jak oni zg³êbiaæ
                           sposoby dzia³ania zaawansowanego oprogramowania i sprzêtu i tropiæ luki pozwalaj¹ce
                           na atak lub wyciek danych oraz przewidywaæ mo¿liwe problemy w ich dzia³aniu.
                           Jon Erickson w ksi¹¿ce Hacking. Sztuka penetracji. Wydanie II omawia te zagadnienia
                           ze œwiata informatyki, które nie mog¹ byæ obce hakerowi. Dziêki tej ksi¹¿ce poznasz
                           m.in. podstawy jêzyka C oraz dowiesz siê, jak wykorzystaæ jego s³aboœci
                           oraz potkniêcia programistów pisz¹cych w tym jêzyku. Zapoznasz siê z podstawami
                           funkcjonowania sieci i zdobêdziesz wiedzê o modelu OSI, a tak¿e nauczysz siê
                           pods³uchiwaæ transmitowane w sieci dane, skanowaæ porty i ³amaæ has³a.
                               • Programowanie w jêzyku C
                               • Model OSI
                               • Pods³uchiwanie sieci
                               • Skanowanie portów
                               • Sposoby ³amania hase³
                               • Szyfrowanie danych i po³¹czeñ
                               • Sposoby atakowania sieci bezprzewodowych
Wydawnictwo Helion
                                                     Oto elementarz prawdziwego hakera!
ul. Koœciuszki 1c
44-100 Gliwice
tel. 032 230 98 63
e-mail: helion@helion.pl
SPIS TRE¥CI




PRZE DMOWA                                                                                                         11

P ODZI} KO W ANI A                                                                                                 12

0X100           WPROWAD ZENIE                                                                                      13

0X200           PR OGR AMOWANIE                                                                                    19
0x210 Istota programowania .....................................................................................20
0x220 Pseudokod ......................................................................................................22
0x230 Struktury sterujÈce ...........................................................................................22
      0x231 If-Then-Else ........................................................................................22
      0x232 PÚtle While/Until ................................................................................24
      0x233 PÚtle for .............................................................................................25
0x240 Podstawowe pojÚcia programistyczne .............................................................26
      0x241 Zmienne .............................................................................................26
      0x242 Operatory arytmetyczne .....................................................................27
      0x243 Operatory porównania .......................................................................28
      0x244 Funkcje ...............................................................................................30
0x250 Zaczynamy brudziÊ sobie rÚce ..........................................................................34
      0x251 WiÚkszy obraz ....................................................................................35
      0x252 Procesor x86 ......................................................................................38
      0x253 JÚzyk asembler ...................................................................................40
0x260 Wracamy do podstaw .....................................................................................53
      0x261 ’añcuchy ............................................................................................53
      0x262 Ze znakiem, bez znaku, dïuga i krótka ................................................57
      0x263 Wska niki ...........................................................................................59
      0x264 ’añcuchy formatujÈce .........................................................................63
0x265 Rzutowanie typów .............................................................................67
                   0x266 Argumenty wiersza poleceñ ...............................................................74
                   0x267 ZasiÚg zmiennych ...............................................................................78
             0x270 Segmentacja pamiÚci .......................................................................................85
                   0x271 Segmenty pamiÚci w jÚzyku C ............................................................92
                   0x272 Korzystanie ze sterty ...........................................................................94
                   0x273 Funkcja malloc() ze sprawdzaniem bïÚdów .........................................96
             0x280 Budujemy na podstawach ...............................................................................98
                   0x281 DostÚp do plików ...............................................................................98
                   0x282 Prawa dostÚpu do plików .................................................................104
                   0x283 Identyfikatory u ytkowników ............................................................105
                   0x284 Struktury ..........................................................................................114
                   0x285 Wska niki do funkcji .........................................................................117
                   0x286 Liczby pseudolosowe ........................................................................118
                   0x287 Gry hazardowe .................................................................................120

             0X300           NADU¿YCI A                                                                                         133
             0x310 Uogólnione techniki nadu yÊ .........................................................................136
             0x320 Przepeïnienia bufora ......................................................................................137
                   0x321 Luki zwiÈzane z przepeïnieniem stosowym .......................................140
             0x330 Eksperymenty z BASH ....................................................................................152
                   0x331 Wykorzystanie rodowiska ...............................................................161
             0x340 Przepeïnienia w innych segmentach ..............................................................170
                   0x341 Podstawowe przepeïnienie na stercie ...............................................170
                   0x342 Przepeïnienia wska ników funkcyjnych .............................................176
             0x350 ’añcuchy formatujÈce ....................................................................................187
                   0x351 Parametry formatujÈce .....................................................................188
                   0x352 Podatno Ê ciÈgów formatujÈcych na ataki ........................................190
                   0x353 Odczyt spod dowolnych adresów pamiÚci ........................................192
                   0x354 Zapis pod dowolnymi adresami pamiÚci ...........................................193
                   0x355 Bezpo redni dostÚp do parametrów .................................................201
                   0x356 U ycie zapisu krótkich liczb caïkowitych ...........................................203
                   0x357 Obej cia z u yciem sekcji dtors .........................................................205
                   0x358 Kolejny sïaby punkt programu notesearch ........................................210
                   0x359 Nadpisywanie globalnej tabeli przesuniÚÊ ........................................212

             0X400           SIEC I                                                                                             217
             0x410 Model OSI .....................................................................................................217
             0x420 Gniazda .........................................................................................................220
                   0x421 Funkcje obsïugujÈce gniazda ............................................................221
                   0x422 Adresy gniazd ..................................................................................223
                   0x423 Sieciowa kolejno Ê bajtów ................................................................224
                   0x424 Konwersja adresu internetowego .....................................................225


6   Hacking. Sztuka penetracji
0x425 Prosty przykïad serwera ....................................................................226
           0x426 Przykïad klienta WWW .....................................................................230
           0x427 Maleñki serwer WWW ......................................................................235
0x430      ZaglÈdamy do ni szych warstw .....................................................................240
           0x431 Warstwa ïÈcza danych ......................................................................240
           0x432 Warstwa sieci ...................................................................................242
           0x433 Warstwa transportowa .....................................................................244
0x440      Podsïuchiwanie w sieci ..................................................................................247
           0X441 Sniffer surowych pakietów ...............................................................249
           0x442 Sniffer libpcap ..................................................................................251
           0x443 Dekodowanie warstw ......................................................................253
           0x444 Aktywne podsïuchiwanie .................................................................263
0x450      Odmowa usïugi .............................................................................................276
           0x451 Zalew pakietów SYN (SYN Flooding) .................................................276
           0x452 Atak Ping of Death ...........................................................................281
           0x453 Atak Teardrop ..................................................................................281
           0x454 Zalew pakietów ping (Ping Flooding) ................................................281
           0x455 Atak ze wzmocnieniem (Amplification) .............................................282
           0x456 Rozproszony atak DoS ......................................................................283
0x460      PrzejÚcie TCP/IP .............................................................................................283
           0x461 RozïÈczanie za pomocÈ RST ..............................................................283
           0x462 PrzejÚcie z kontynuacjÈ .....................................................................289
0x470      Skanowanie portów ......................................................................................289
           0x471 Ukryte skanowanie SYN ....................................................................289
           0x472 Skanowanie FIN, X-mas i Null ...........................................................290
           0x473 Skanowanie z ukrycia .......................................................................290
           0x474 Skanowanie z u yciem bezczynnego komputera ...............................291
           0x475 Zabezpieczenie wyprzedzajÈce (Shroud) ...........................................293
0x480      Id i wïam siÚ gdzie .....................................................................................298
           0x481 Analiza z u yciem GDB .....................................................................299
           0x482 Prawie ma znaczenie ........................................................................301
           0x483 Shellcode wiÈ Ècy port .....................................................................304

0X500           SHE LLCODE                                                                                          309
0x510 Asembler a C .................................................................................................309
      0x511 Linuksowe wywoïania systemowe w asemblerze .............................312
0x520 ¥cie ka do shellcode ......................................................................................315
      0x521 Instrukcje asemblera wykorzystujÈce stos .........................................315
      0x522 Badanie za pomocÈ GDB ..................................................................317
      0x523 Usuwanie bajtów zerowych ..............................................................319
0x530 Kod wywoïujÈcy powïokÚ ..............................................................................324
      0x531 Kwestia uprawnieñ ...........................................................................328
      0x532 Skracamy jeszcze bardziej .................................................................331



                                                                                                        Spis tre ci       7
0x540 Kod powïoki wiÈ Ècy port .............................................................................332
                   0x541 Duplikowanie standardowych deskryptorów plików .........................336
                   0x542 RozgaïÚziajÈce struktury sterujÈce ....................................................338
             0x550 Shellcode nawiÈzujÈcy poïÈczenie powrotne .................................................343

             0X600           ¥R OD KI ZAPOBI EGAWC ZE                                                                         349
             0x610 ¥rodki zapobiegawcze, które wykrywajÈ .......................................................350
             0x620 Demony systemowe ......................................................................................351
                   0x621 Bïyskawiczne wprowadzenie do sygnaïów .......................................352
                   0x622 Demon tinyweb ................................................................................354
             0x630 NarzÚdzia pracy .............................................................................................358
                   0x631 NarzÚdzie nadu ywajÈce tinywebd ...................................................359
             0x640 Pliki dziennika ...............................................................................................364
                   0x641 Wmieszaj siÚ w tïum ........................................................................365
             0x650 Przeoczywszy oczywiste ................................................................................366
                   0x651 Krok po kroku ...................................................................................367
                   0x652 Ponowne skïadanie wszystkiego ......................................................371
                   0x653 Robocze procesy potomne ................................................................377
             0x660 Zaawansowana sztuka kamufla u .................................................................378
                   0x661 Faïszowanie rejestrowanego adresu IP .............................................379
                   0x662 Nierejestrowane nadu ycie ...............................................................383
             0x670 Caïa infrastruktura .........................................................................................386
                   0x671 Ponowne wykorzystanie gniazda ......................................................386
             0x680 Przemyt ïadunku ............................................................................................390
                   0x681 Kodowanie ïañcuchów .....................................................................391
                   0x682 Jak ukryÊ puïapkÚ? ...........................................................................394
             0x690 Ograniczenia bufora ......................................................................................395
                   0x691 Polimorficzny kod powïoki z drukowalnymi znakami ASCII ...............397
             0x6a0 Zabezpieczenia wzmacniajÈce .......................................................................408
             0x6b0 Niewykonywalny stos ....................................................................................408
                   0x6b1 Powracanie do funkcji biblioteki libc .................................................409
                   0x6b2 Powrót do funkcji system() ...............................................................409
             0x6c0 Randomizacja przestrzeni stosu .....................................................................411
                   0x6c1 Badanie za pomocÈ BASH i GDB .......................................................413
                   0x6c2 Odbijanie od linux-gate ....................................................................417
                   0x6c3 Wiedza stosowana ...........................................................................420
                   0x6c4 Pierwsza próba .................................................................................421
                   0x6c5 Gramy w ko ci ..................................................................................422

             0X700           KRYP TOLOGIA                                                                                     425
             0x710 Teoria informacji ............................................................................................426
                   0x711 Bezwarunkowe bezpieczeñstwo .......................................................426
                   0x712 Szyfr z kluczem jednorazowym .........................................................426


8   Hacking. Sztuka penetracji
0x713 Kwantowa dystrybucja kluczy ...........................................................427
          0x714 Bezpieczeñstwo obliczeniowe ...........................................................428
0x720     Rozlegïo Ê algorytmów .................................................................................429
          0x721 Notacja asymptotyczna .....................................................................430
0x730     Szyfrowanie symetryczne ...............................................................................430
          0x731 Kwantowy algorytm przeszukiwania autorstwa Lova Grovera ...........432
0x740     Szyfrowanie asymetryczne .............................................................................432
          0x741 RSA ..................................................................................................433
          0x742 Kwantowy algorytm rozkïadu na czynniki autorstwa Petera Shora ....437
0x750     Szyfry hybrydowe ..........................................................................................438
          0x751 Ataki z ukrytym po rednikiem ...........................................................439
          0x752 „Odciski palców” komputerów w protokole SSH ...............................443
          0x753 Rozmyte „odciski palców” ................................................................447
0x760     ’amanie haseï ...............................................................................................451
          0x761 Ataki sïownikowe .............................................................................453
          0x762 Ataki na zasadzie peïnego przeglÈdu ................................................455
          0x763 Tablica wyszukiwania skrótów .........................................................457
          0x764 Macierz prawdopodobieñstwa haseï ................................................457
0x770     Szyfrowanie w sieci bezprzewodowej 802.11b ..............................................467
          0x771 Protokóï Wired Equivalent Privacy (WEP) ..........................................468
          0x772 Szyfr strumieniowy RC4 ....................................................................469
0x780     Ataki na WEP ................................................................................................470
          0x781 Ataki na zasadzie peïnego przeglÈdu w trybie offline .......................470
          0x782 Ponowne u ycie strumienia klucza ....................................................471
          0x783 Tablice sïownikowe z wektorami IV ..................................................472
          0x784 Przekierowanie IP .............................................................................473
          0x785 Atak Fluhrera, Mantina i Shamira (FMS) ............................................474

0X800          P ODSUMOWANIE                                                                                      485
0x810 Bibliografia i dodatkowe informacje ..............................................................486
0x820 Kody ródïowe ..............................................................................................487

O P ’YC IE C D                                                                                                    489

SKOR OWID Z                                                                                                       491




                                                                                                      Spis tre ci       9
0x200
                      PROGRAMOWANIE




Haker to termin u ywany do okre lenia zarówno piszÈcych kod, jak
i tych, którzy wykorzystujÈ znajdujÈce siÚ w nim bïÚdy. ChoÊ obie
grupy hakerów majÈ ró ne cele, to i jedni, i drudzy stosujÈ podobne
techniki rozwiÈzywania problemów. A ze wzglÚdu na fakt, e umiejÚt-
no Ê programowania pomaga tym, którzy wykorzystujÈ bïÚdy w kodzie,
za zrozumienie metod zastosowania pomaga tym, którzy programujÈ,
wielu hakerów robi obie rzeczy jednocze nie. InteresujÈce rozwiÈzania istniejÈ
i w zakresie technik pisania eleganckiego kodu, i technik sïu Ècych do wykorzysty-
wania sïabo ci programów. Hakerstwo to w rzeczywisto ci akt znajdowania pomy-
sïowych i nieintuicyjnych rozwiÈzañ problemów.
    Metody stosowane w narzÚdziach wykorzystujÈcych sïabo ci programów zwy-
kle sÈ zwiÈzane z zastosowaniem reguï funkcjonowania komputera w sposób, któ-
rego nigdy nie brano pod uwagÚ — pozornie magiczne rezultaty osiÈga siÚ zwykle
po skupieniu siÚ na omijaniu zaimplementowanych zabezpieczeñ. Metody u ywa-
ne podczas pisania programów sÈ podobne, bo równie wykorzystujÈ reguïy funk-
cjonowania komputera w nowy i pomysïowy sposób, jednak w tym przypadku koñco-
wym celem jest osiÈgniÚcie najbardziej wydajnego lub najkrótszego kodu ródïowego.
Istnieje nieskoñczenie wiele programów, które mo na napisaÊ w celu wykonania do-
wolnego zadania, jednak wiÚkszo Ê z istniejÈcych rozwiÈzañ jest niepotrzebnie
obszerna, zïo ona i niedopracowana. Pozostaïa niewielka ich liczba to programy
niedu e, wydajne i estetyczne. Ta wïa ciwo Ê programów nosi nazwÚ elegancji, za
przemy lane i pomysïowe rozwiÈzania prowadzÈce do takiej wydajno ci nazywane
sÈ sztuczkami (ang. hacks). Hakerzy stojÈcy po obu stronach metodyki programowania
doceniajÈ zarówno piÚkno eleganckiego kodu, jak i geniusz pomysïowych sztuczek.
W wiecie biznesu mniejszÈ wagÚ przykïada siÚ do przemy lanych metod pro-
             gramowania i eleganckiego kodu, a wiÚkszÈ do tworzenia funkcjonalnego kodu w
             jak najkrótszym czasie i jak najtaniej. Ze wzglÚdu na gwaïtowny wzrost mocy obli-
             czeniowej oraz dostÚpno ci pamiÚci po wiÚcenie dodatkowych piÚciu godzin na
             opracowanie nieco szybszego i mniej wymagajÈcego pod wzglÚdem pamiÚci frag-
             mentu kodu po prostu nie opïaca siÚ, gdy mamy do czynienia z nowoczesnymi kom-
             puterami dysponujÈcymi gigahercowymi cyklami procesora i gigabajtami pamiÚci.
             Podczas gdy optymalizacje czasu i wykorzystania pamiÚci pozostajÈ niezauwa one
             przez wiÚkszo Ê (z wyjÈtkiem wyrafinowanych) u ytkowników, nowa funkcjonal-
             no Ê ma potencjaï marketingowy. Kiedy najwa niejszym kryterium sÈ pieniÈdze,
             po wiÚcanie czasu na opracowywanie przemy lanych sztuczek optymalizacyjnych
             nie ma po prostu sensu.
                 ElegancjÚ programowania pozostawiono hakerom, hobbistom komputerowym,
             których celem nie jest zarabianie, lecz wyci niÚcie wszystkiego, co siÚ da, z ich sta-
             rych maszyn Commodore 64, autorom programów wykorzystujÈcych bïÚdy, piszÈ-
             cym niewielkie i niesamowite fragmenty kodu, dziÚki którym potrafiÈ przedostawaÊ
             siÚ przez wÈskie szczeliny systemów zabezpieczeñ, oraz wszystkim innym doceniajÈ-
             cym warto Ê szukania i znajdowania najlepszych mo liwych rozwiÈzañ. SÈ to osoby
             zachwycajÈce siÚ mo liwo ciami oferowanymi przez programowanie i dostrzegajÈce
             piÚkno eleganckich fragmentów kodu oraz geniusz przemy lanych sztuczek. Poznanie
             istoty programowania jest niezbÚdne do zrozumienia, w jaki sposób mo na wykorzy-
             stywaÊ sïabo ci programów, dlatego te programowanie to naturalny punkt wyj cia
             dla naszych rozwa añ.


0x210 Istota programowania
             Programowanie to pojÚcie niezmiernie naturalne i intuicyjne. Program jest tylko
             seriÈ instrukcji zapisanych w okre lonym jÚzyku. Programy wystÚpujÈ wszÚdzie
             i nawet technofoby codziennie korzystajÈ z programów. Opisywanie drogi dojazdu
             w jakie miejsce, przepisy kulinarne, rozgrywki piïkarskie i spirale DNA to sÈ ró -
             nego typu programy. Typowy „program” opisu dojazdu samochodem w konkretne
             miejsce mo e wyglÈdaÊ tak:

             Najpierw zjed w dó Alejæ Ko ciuszki, prowadzæcæ na wschód. Jed niæ
             do momentu, kiedy zobaczysz po prawej stronie ko ció . Je eli ulica búdzie
             zablokowana ze wzglúdu na prowadzone roboty, skrúè w prawo w ul. Moniuszki,
             potem skrúè w lewo w ul. Prusa i w ko cu skrúè w prawo w ul. Orzeszkowej.
             W przeciwnym razie mo esz po prostu kontynuowaè jazdú Alejæ Ko ciuszki
             i skrúciè w ul. Orzeszkowej. Jed niæ i skrúè w ul. Docelowæ. Jed niæ
             jakie 8 kilometrów — nasz dom búdzie siú znajdowa po prawej stronie.
             Dok adny adres to ul. Docelowa 743.

                 Ka dy, kto zna jÚzyk polski, pojmie podane instrukcje i bÚdzie mógï kierowaÊ
             siÚ nimi podczas jazdy. Bez wÈtpienia nie zapisano ich zbyt bïyskotliwie, ale sÈ jed-
             noznaczne i zrozumiaïe.


20   0x200
Jednak komputer nie zna jÚzyka polskiego — rozumie jedynie jÚzyk maszynowy
              (ang. machine language). W celu poinstruowania go, aby wykonaï pewnÈ czynno Ê,
              instrukcjÚ tÚ nale y zapisaÊ w zrozumiaïym dla niego jÚzyku. Jednak e jÚzyk ma-
              szynowy jest bardzo ezoteryczny i trudny do opanowania. Skïada siÚ z serii bitów
              oraz bajtów i ró ni siÚ, w zale no ci od danej architektury komputerowej. Tak wiÚc
              w celu napisania programu w jÚzyku maszynowym dla procesora z rodziny Intel x86
              nale y okre liÊ warto Ê zwiÈzanÈ z ka dÈ instrukcjÈ, sposób interakcji poszczególnych
              instrukcji oraz mnóstwo innych niskopoziomowych szczegóïów. Tego rodzaju pro-
              gramowanie jest bardzo niewdziÚcznym oraz kïopotliwym zadaniem i z pewno ciÈ
              nie jest intuicyjne.
                  Do pokonania komplikacji zwiÈzanych z pisaniem programów w jÚzyku maszy-
              nowym potrzebny jest translator. JednÈ z form translatora jÚzyka maszynowego jest
              asembler. To program, który tïumaczy jÚzyk asemblera na kod zapisany w jÚzyku
              maszynowym. JÚzyk asemblera jest bardziej przystÚpny od kodu maszynowego,
              poniewa dla ró nych instrukcji i zmiennych wykorzystuje nazwy (mnemoniki), a nie
              same warto ci liczbowe. Jednak jÚzyk asemblera wciÈ jest daleki od intuicyjnego.
              Nazwy instrukcji sÈ ezoteryczne, a sam jÚzyk wciÈ jest zale ny od architektury.
              Oznacza to, e tak samo, jak jÚzyk maszynowy dla procesorów Intel x86 ró ni siÚ
              od jÚzyka maszynowego dla procesorów Sparc, jÚzyk asemblera x86 jest ró ny od
              jÚzyka asemblera Sparc. ¿aden program napisany przy u yciu jÚzyka asemblera dla
              architektury jednego procesora nie bÚdzie dziaïaï w architekturze innego procesora.
              Je eli program zostaï napisany w jÚzyku asemblera x86, musi zostaÊ przepisany, aby
              mo na byïo uruchomiÊ go w architekturze Sparc. Ponadto w celu napisania wydaj-
              nego programu w jÚzyku asemblera nale y znaÊ wiele niskopoziomowych szczegó-
              ïów, dotyczÈcych architektury danego procesora.
                  Problemów tych mo na uniknÈÊ przy u yciu kolejnej formy translatora, noszÈ-
              cego nazwÚ kompilatora (ang. compiler). Kompilator konwertuje kod zapisany w jÚzy-
              ku wysokopoziomowym do postaci kodu maszynowego. JÚzyki wysokopoziomowe sÈ
              o wiele bardziej intuicyjne od jÚzyka asemblera i mogÈ byÊ konwertowane do wielu
              ró nych typów jÚzyka maszynowego dla odmiennych architektur procesorów. Ozna-
              cza to, e je li zapisze siÚ program w jÚzyku wysokiego poziomu, ten sam kod mo e
              zostaÊ skompilowany przez kompilator do postaci kodu maszynowego dla ró nych
              architektur. C, C++ lub FORTRAN to przykïady jÚzyków wysokopoziomowych.
              Program napisany w takim jÚzyku jest o wiele bardziej czytelny1 od jÚzyka asem-
              blera lub maszynowego, choÊ wciÈ musi byÊ zgodny z bardzo surowymi reguïami
              dotyczÈcymi sposobu wyra ania instrukcji, poniewa w przeciwnym razie kompila-
              tor nie bÚdzie w stanie ich zrozumieÊ.




1
    Oczywi cie pod warunkiem, e przez czytelny rozumiemy taki, który przypomina jÚzyk angielski
    — przyp. tïum.



                                                                               Programowanie    21
0x220 Pseudokod
             Programi ci dysponujÈ jeszcze jednym rodzajem jÚzyka programowania, noszÈcym
             nazwÚ pseudokodu. Pseudokod (ang. pseudo-code) to po prostu wyra enia zapisane
             w jÚzyku naturalnym, ustawione w strukturÚ ogólnie przypominajÈcÈ jÚzyk wyso-
             kopoziomowy. Nie jest on rozumiany przez kompilatory, asemblery ani kompute-
             ry, ale stanowi przydatny sposób skïadania instrukcji. Pseudokod nie jest dobrze
             zdefiniowany. W rzeczywisto ci wiele osób zapisuje pseudokod odmiennie. Jest to
             rodzaj nieokre lonego, brakujÈcego ogniwa miÚdzy jÚzykami naturalnymi, takimi
             jak angielski lub polski, a wysokopoziomowymi jÚzykami programowania, takimi
             jak C lub Pascal. Pseudokod stanowi wietne wprowadzenie do uniwersalnych
             zaïo eñ programistycznych.


0x230 Struktury sterujÈce
             Bez struktur sterujÈcych program byïby jedynie seriÈ kolejno wykonywanych instruk-
             cji. Jest to wystarczajÈce w przypadku bardzo prostych programów, ale wiÚkszo Ê
             programów, takich jak np. opis dojazdu, taka nie jest. Prezentowany opis dojazdu
             zawieraï instrukcje: Jed niÈ do momentu, kiedy zobaczysz po prawej stronie ko cióï.
             Je eli ulica bÚdzie zablokowana ze wzglÚdu na prowadzone roboty… Instrukcje te
             nazywamy strukturami sterujÈcymi, poniewa zmieniajÈ przebieg wykonywania
             programu z prostego, sekwencyjnego, na bardziej zïo ony i u yteczny.

             0x231       If-Then-Else
             W naszym opisie dojazdu Aleja Ko ciuszki mo e byÊ w remoncie. Do rozwiÈzania
             problemu wynikajÈcego z tej sytuacji potrzebujemy specjalnego zestawu instrukcji.
             Je eli zdefiniowane okoliczno ci nie wystÈpiÈ (remont), bÚdÈ wykonywane standardo-
             we instrukcje. Tego rodzaju specjalne przypadki mo na wziÈÊ pod uwagÚ w progra-
             mie, korzystajÈc z jednej z najbardziej naturalnych struktur sterujÈcych: if-then-else
             (je eli-wówczas-w przeciwnym przypadku). Ogólnie wyglÈda to mniej wiÚcej tak:

             If (warunek) then
             {
             Zestaw instrukcji do wykonania, gdy warunek jest spe niony;
             }
             Else
             {
             Zestaw instrukcji do wykonania, gdy warunek nie jest spe niony;
             }


                W tej ksiÈ ce bÚdziemy posïugiwali siÚ pseudokodem przypominajÈcym jÚzyk C,
             wiÚc ka da instrukcja bÚdzie zakoñczona rednikiem, a ich zbiory bÚdÈ grupowane
             za pomocÈ nawiasów klamrowych i wyró niane wciÚciem. Pseudokod struktury
             if-then-else dla wskazówek dojazdu mógïby przedstawiaÊ siÚ nastÚpujÈco:




22   0x200
Jed w dó Alejæ Ko ciuszki;
Je eli (ulica zablokowana)
{
  Skrúè w prawo w ul. Moniuszki;
  Skrúè w lewo w ul. Prusa;
  Skrúè w prawo w ul. Orzeszkowej;
}
else
{
  Skrúè w prawo w ul. Orzeszkowej;
}


    Ka da instrukcja znajduje siÚ w osobnym wierszu, a ró ne zestawy instrukcji
warunkowych sÈ zgrupowane wewnÈtrz nawiasów klamrowych i dla zwiÚkszenia
czytelno ci zastosowano dla nich wciÚcie. W C i wielu innych jÚzykach programo-
wania sïowo kluczowe then jest domniemane i tym samym pomijane, wiÚc pomi-
nÚli my je równie w pseudokodzie.
    Oczywi cie, istniejÈ jÚzyki, których skïadnia wymaga zastosowania sïowa klu-
czowego then — przykïadami mogÈ tu byÊ BASIC, Fortran, a nawet Pascal. Tego
typu ró nice syntaktyczne miÚdzy jÚzykami programowania sÈ niemal nieistotne,
jako e podstawowa struktura jest taka sama. Gdy programista zrozumie zaïo enia
tych jÚzyków, nauczenie siÚ ró nych odmian syntaktycznych jest stosunkowo ïatwe.
Poniewa w dalszych rozdziaïach bÚdziemy programowali w jÚzyku C, prezento-
wany pseudokod bÚdzie przypominaï ten jÚzyk. Nale y jednak pamiÚtaÊ, e mo e
on przyjmowaÊ ró ne postaci.
    InnÈ powszechnÈ reguïÈ skïadni podobnej do C jest sytuacja, w której zestaw
instrukcji umieszczonych w nawiasach klamrowych zawiera tylko jednÈ instrukcjÚ.
Dla zwiÚkszenia czytelno ci wciÈ warto dla takiej instrukcji zastosowaÊ wciÚcie,
ale nie jest ono wymagane. Zgodnie z tÈ reguïÈ mo na wiÚc napisaÊ wcze niej przed-
stawiony opis dojazdu tak, aby uzyskaÊ równowa ny fragment pseudokodu:

Jed w dó Alejæ Ko ciuszki;
Je eli (ulica zablokowana)
{
  Skrúè w prawo w ul. Moniuszki;
  Skrúè w lewo w ul. Prusa;
  Skrúè w prawo w ul. Orzeszkowej;
}
else
  Skrúè w prawo w ul. Orzeszkowej;


   Reguïa mówiÈca o zestawach instrukcji dotyczy wszystkich struktur sterujÈcych
opisywanych w niniejszej ksiÈ ce, a samÈ reguïÚ równie mo na zapisaÊ w pseu-
dokodzie.




                                                               Programowanie   23
If (w zestawie instrukcji znajduje siú tylko jedna instrukcja)
               U ycie nawiasów klamrowych do zgrupowania instrukcji jest opcjonalne;
             Else
             {
               U ycie nawiasów klamrowych jest niezbúdne;
               Poniewa musi istnieè logiczny sposób zgrupowania tych instrukcji;
             }


                 Nawet opis skïadni mo na potraktowaÊ jak program. Istnieje wiele odmian struk-
             tury if-then-else, np. instrukcje select i case, ale logika pozostaje taka sama: je eli
             stanie siÚ tak, zrób to i to, w przeciwnym przypadku wykonaj, co poni ej (a poni ej
             mogÈ siÚ znajdowaÊ kolejne instrukcje if-then).

             0x232        PÚtle While/Until
             Innym podstawowym pojÚciem programistycznym jest struktura sterujÈca while,
             bÚdÈca rodzajem pÚtli. Programista czÚsto chce wykonaÊ zestaw instrukcji kilka razy.
             Program mo e wykonaÊ to zadanie, stosujÈc pÚtlÚ, ale wymaga to okre lenia warun-
             ków jej zakoñczenia, aby nie trwaïa w nieskoñczono Ê. PÚtla while wykonuje podany
             zestaw instrukcji, dopóki warunek jest prawdziwy. Prosty program dla gïodnej
             myszy mógïby wyglÈdaÊ nastÚpujÈco:

             While (jeste g odna)
             {
               Znajd jakie jedzenie;
               Zjedz jedzenie;
             }


                 Te dwa zestawy instrukcji za instrukcjÈ while bÚdÈ powtarzane, dopóki mysz
             bÚdzie gïodna. Ilo Ê po ywienia odnalezionego przez mysz przy ka dej próbie mo e
             wahaÊ siÚ od maïego okruszka po caïy bochen chleba. Podobnie liczba wykonañ
             zestawu instrukcji w pÚtli while zale y od ilo ci po ywienia znalezionego przez mysz.
                 OdmianÈ pÚtli while jest pÚtla until, wykorzystywana w Perlu (w C skïadnia
             ta nie jest u ywana). PÚtla until jest po prostu pÚtlÈ while z odwróconym warunkiem.
             Ten sam program dla myszy zapisany z u yciem pÚtli until wyglÈdaïby nastÚpujÈco:

             Until (nie jeste g odna)
             {
               Znajd jakie jedzenie;
               Zjedz jedzenie;
             }


                Logicznie ka da instrukcja podobna do until mo e byÊ przeksztaïcona w pÚtlÚ
             while. Opis dojazdu zawieraï zdanie: „Jed niÈ do momentu, kiedy zobaczysz po
             prawej stronie ko cióï”. Mo emy to w prosty sposób przeksztaïciÊ w standardowÈ
             pÚtlÚ while — wystarczy, e odwrócimy warunek:




24   0x200
While (nie ma ko cio a po prawej stronie)
  Jed Alejæ Ko ciuszki;


0x233        PÚtle for
KolejnÈ strukturÈ sterujÈcÈ jest pÚtla for, wykorzystywana wtedy, gdy programista
chce, aby pÚtla wykonaïa okre lonÈ liczbÚ iteracji. Instrukcja dojazdu: „Jed niÈ
jakie 8 kilometrów” przeksztaïcona do pÚtli for mogïaby wyglÈdaÊ nastÚpujÈco:
For (8 iteracji)

  Jed   prosto 1 kilometr;


    W rzeczywisto ci pÚtla for jest po prostu pÚtlÈ while z licznikiem. Powy szÈ
instrukcjÚ mo na równie dobrze zapisaÊ tak:

Ustaw licznik na 0
While (licznik jest mniejszy od 8)
{
  Jed prosto 1 kilometr;
  Dodaj 1 do licznika;
}


   Skïadnia pseudokodu dla pÚtli for sprawia, e jest to jeszcze bardziej widoczne:

For (i=0; i<8; i++)
  Jed prosto 1 kilometr;


    W tym przypadku licznik nosi nazwÚ i, a instrukcja for jest podzielona na trzy
sekcje oddzielone rednikami. Pierwsza sekcja deklaruje licznik i ustawia jego po-
czÈtkowÈ warto Ê — w tym przypadku 0. Druga sekcja przypomina instrukcjÚ while
z licznikiem — dopóki licznik speïnia podany warunek, kontynuuj pÚtlÚ. Trzecia
i ostatnia sekcja opisuje, co ma siÚ dziaÊ z licznikiem przy ka dej iteracji. W tym
przypadku i++ jest skróconym sposobem na powiedzenie: „Dodaj 1 do licznika
o nazwie i”.
    Zastosowanie wszystkich omówionych struktur sterujÈcych umo liwia przeksztaï-
cenie opisu dojazdu ze strony 6 w poni szy pseudokod przypominajÈcy jÚzyk C:

Rozpocznij jazdú na wschód Alejæ Ko ciuszki;
While (po prawej stronie nie ma ko cio a)
   Jed Alejæ Ko ciuszki;
If (ulica zablokowana)
{
   Skrúè w prawo w ul. Moniuszki);
   Skrúè w lewo w ul. Prusa);
   Skrúè w prawo w ul. Orzeszkowej);
}




                                                                Programowanie    25
Else
                Skrúè(prawo, ul. Orzeszkowej);
             Skrúè(lewo, ul. Docelowa);
             For (i=0; i<8; i++)
             {
                Jed prosto 1 kilometr;
             }
             Zatrzymaj siú przy ul. Docelowej 743;



0x240 Podstawowe pojÚcia programistyczne
             W kolejnych punktach zostanÈ przedstawione podstawowe pojÚcia programistyczne.
             SÈ one wykorzystywane w wielu jÚzykach programowania, ró niÈ siÚ jedynie pod
             wzglÚdem syntaktycznym. Podczas prezentacji bÚdÈ integrowane z przykïadami
             w pseudokodzie przypominajÈcym skïadniÚ jÚzyka C. Na koñcu pseudokod bÚdzie
             bardzo przypominaï kod napisany w jÚzyku C.

             0x241       Zmienne
             Licznik wykorzystywany w pÚtli for jest rodzajem zmiennej. O zmiennej mo emy
             my leÊ jak o obiekcie przechowujÈcym dane, które mogÈ byÊ zmieniane — stÈd
             nazwa. IstniejÈ równie zmienne, których warto ci nie sÈ zmieniane, i trafnie nazywa
             siÚ je staïymi. W przykïadzie motoryzacyjnym jako zmiennÈ mo emy potraktowaÊ
             prÚdko Ê samochodu, natomiast kolor lakieru samochodu byïby staïÈ. W pseudo-
             kodzie zmienne sÈ po prostu pojÚciami abstrakcyjnymi, natomiast w C (i wielu in-
             nych jÚzykach) zmienne przed wykorzystaniem muszÈ byÊ zadeklarowane i nale y
             okre liÊ ich typ. Jest tak dlatego, e program napisany w C bÚdzie kompilowany
             do postaci programu wykonywalnego. Podobnie jak przepis kucharski, w którym
             przed faktycznymi instrukcjami wymieniane sÈ wszystkie potrzebne skïadniki, de-
             klaracje zmiennych pozwalajÈ dokonaÊ przygotowañ przed przej ciem do faktycznej
             tre ci programu. Ostatecznie wszystkie zmienne sÈ przechowywane gdzie w pamiÚci,
             a ich deklaracje pozwalajÈ kompilatorowi wydajniej uporzÈdkowaÊ pamiÚÊ. Jednak
             na koniec, mimo wszystkich deklaracji typów zmiennych, wszystko odbywa siÚ
             w pamiÚci.
                 W jÚzyku C dla ka dej zmiennej okre lany jest typ, opisujÈcy informacje, które
             bÚdÈ przechowywane w tej zmiennej. Do najczÚ ciej stosowanych typów zalicza-
             my int (liczby caïkowite), float (liczby zmiennoprzecinkowe) i char (pojedyncze
             znaki). Zmienne sÈ deklarowane poprzez u ycie tych sïów kluczowych przed nazwÈ
             zmiennej, co zobrazowano na poni szym przykïadzie.

             int a, b;
             float k;
             char z;


                Zmienne a i b sÈ zadeklarowane jako liczby caïkowite, k mo e przyjmowaÊ warto-
             ci zmiennoprzecinkowe (np. 3,14), a z powinna przechowywaÊ warto Ê znakowÈ,



26   0x200
takÈ jak A lub w. Warto ci mo na przypisywaÊ zmiennym podczas deklaracji lub
w dowolnym pó niejszym momencie. Sïu y do tego operator =.

int a = 13, b;
float k;
char z = 'A';

k = 3.14;
z = 'w';
b = a + 5;


   Po wykonaniu powy szych instrukcji zmienna a bÚdzie posiadaïa warto Ê 13,
zmienna k bÚdzie zawieraïa liczbÚ 3,14, a zmienna b bÚdzie miaïa warto Ê 18, po-
niewa 13 plus 5 równa siÚ 18. Zmienne sÈ po prostu sposobem pamiÚtania warto ci,
jednak w jÚzyku C nale y najpierw zadeklarowaÊ typ ka dej zmiennej.

0x242        Operatory arytmetyczne
Instrukcja b = a + 7 jest przykïadem bardzo prostego operatora arytmetycznego.
W jÚzyku C dla ró nych operacji matematycznych wykorzystywane sÈ poni sze
symbole.
    Pierwsze cztery operatory powinny wyglÈdaÊ znajomo. Redukcja modulo mo e
stanowiÊ nowe pojÚcie, ale jest to po prostu reszta z dzielenia. Je eli a ma warto Ê
13, to 13 podzielone przez 5 równa siÚ 2, a reszta wynosi 3, co oznacza, e a % 5 = 3.
Ponadto skoro zmienne a i b sÈ liczbami caïkowitymi, po wykonaniu instrukcji
b = a / 5, zmienna b bÚdzie miaïa warto Ê 2, poniewa jest to czÚ Ê wyniku bÚdÈca
liczbÈ caïkowitÈ. Do przechowania bardziej poprawnego wyniku, czyli 2,6, musi
zostaÊ u yta zmienna typu float (zmiennoprzecinkowa).

 Operacja               Symbol                 Przykïad
 Dodawanie              +                      b = a + 5
 Odejmowanie            -                      b = a - 5
 Mno enie               *                      b = a * 5
 Dzielenie              /                      b = a / 5
 Redukcja modulo        %                      b = a % 5


   Aby program korzystaï z tych zaïo eñ, musimy mówiÊ w jego jÚzyku. JÚzyk C
dostarcza kilku skróconych form zapisu tych operacji arytmetycznych. Jedna z nich
zostaïa przedstawiona wcze niej i jest czÚsto wykorzystywana w pÚtlach for.

 Peïne wyra enie        Skrót                  Wyja nienie
 i = i + 1              i++ lub ++i            Dodaje 1 do warto ci zmiennej.
 i = i - 1              i-- lub i--            Odejmuje 1 od warto ci zmiennej.



                                                                  Programowanie   27
Te skrócone wyra enia mogÈ byÊ ïÈczone z innymi operacjami arytmetycznymi
             w celu utworzenia bardziej zïo onych wyra eñ. Wówczas staje siÚ widoczna ró nica
             miÚdzy i++ i ++i. Pierwsze wyra enie oznacza: „ZwiÚksz warto Ê i o 1 po przepro-
             wadzeniu operacji arytmetycznej”, natomiast drugie: „ZwiÚksz warto Ê i o 1 przed
             przeprowadzeniem operacji arytmetycznej”. Poni szy przykïad pozwoli to lepiej
             zrozumieÊ.

             int a, b;
             a = 5
             b = a++ * 6;


                Po wykonaniu tego zestawu instrukcji zmienna b bÚdzie miaïa warto Ê 30, nato-
             miast zmienna a bÚdzie miaïa warto Ê 6, poniewa skrócony zapis b = a++ * 6 jest
             równowa ny poni szym instrukcjom.

             b = a * 6;
             a = a + 1;


                Je eli jednak zostanie u yta instrukcja b = ++a * 6, kolejno Ê dodawania zostanie
             zmieniona i otrzymamy odpowiednik poni szych instrukcji.

             a = a + 1;
             b = a * 6;


                Poniewa kolejno Ê wykonywania dziaïañ zmieniïa siÚ, w powy szym przypad-
             ku zmienna b bÚdzie miaïa warto Ê 36, natomiast warto Ê zmiennej a wciÈ bÚdzie
             wynosiïa 6.
                CzÚsto w programach musimy zmodyfikowaÊ zmiennÈ w danym miejscu. Przy-
             kïadowo mo emy dodaÊ dowolnÈ warto Ê, takÈ jak 12, i przechowaÊ wynik w tej
             samej zmiennej (np. i = i + 12) Zdarza siÚ to tak czÚsto, e równie utworzono
             skróconÈ formÚ tej instrukcji.

              Peïne wyra enie       Skrót      Wyja nienie
              i = i + 12            i+=12      Dodaje okre lonÈ warto Ê do warto ci zmiennej.
              i = i - 12            i-=12      Odejmuje okre lonÈ warto Ê od warto ci zmiennej.
              i = i * 12            i*=12      Mno y okre lonÈ warto Ê przez warto Ê zmiennej.
              i = i / 12            i/=12      Dzieli warto Ê zmiennej przez okre lonÈ warto Ê.


             0x243          Operatory porównania
             Zmienne sÈ czÚsto wykorzystywane w instrukcjach warunkowych wcze niej opisanych
             struktur sterujÈcych, a te instrukcje warunkowe opierajÈ siÚ na jakiego rodzaju
             porównaniu. W jÚzyku C operatory porównania wykorzystujÈ skróconÈ skïadniÚ,
             która jest stosunkowo powszechna w innych jÚzykach programowania.


28   0x200
Warunek                       Symbol                   Przykïad
 Mniejsze ni                   <                        (a < b)
 WiÚksze ni                    >                        (a < b)
 Mniejsze lub równe            <=                       (a <= b)
 WiÚksze lub równe             >=                       (a >= b)
 Równe                         ==                       (a == b)
 Nie równa siÚ                 !=                       (a != b)


   WiÚkszo Ê z tych operatorów jest zrozumiaïa, jednak e nale y zauwa yÊ, e
w skrócie porównania równo ci wykorzystywane sÈ dwa znaki równo ci. Jest to wa ne
rozró nienie, poniewa podwójny znak równo ci jest stosowany do sprawdzenia
równo ci, natomiast jeden znak równo ci jest u ywany do przypisania warto ci
zmiennej. Instrukcja a = 7 oznacza: „Umie Ê w zmiennej a warto Ê 7”, natomiast
a == 7 oznacza: „Sprawd , czy warto Ê zmiennej a wynosi 7”. (Niektóre jÚzyki pro-
gramowania, takie jak Pascal, wykorzystujÈ do przypisywania warto ci zmiennym
nastÚpujÈcy znak — := — aby wyeliminowaÊ ryzyko bïÚdnego zrozumienia kodu).
Nale y te zwróciÊ uwagÚ, e wykrzyknik zwykle oznacza nie. Ten symbol mo e byÊ
wykorzystany do odwrócenia dowolnego wyra enia.

!(a < b)   jest równowa ne    (a >= b)


    Operatory porównania mogÈ byÊ ïÈczone ze sobÈ za pomocÈ skrótów dla ope-
ratorów logicznych OR i AND.

  Operator logiczny      Symbol                     Przykïad
  OR                     ||                         ((a < b) || (a < c))
  AND                    &&                         ((a < b) && !(a < c))


    Przykïadowa instrukcja zawierajÈca dwa mniejsze warunki poïÈczone operato-
rem OR zostanie oszacowana jako prawdziwa, je eli warto Ê zmiennej a bÚdzie mniej-
sza od warto ci zmiennej b LUB warto Ê zmiennej a bÚdzie mniejsza od warto ci
zmiennej c. Podobnie przykïadowa instrukcja zawierajÈca dwa mniejsze warunki
poïÈczone operatorem AND zostanie oszacowana jako prawdziwa, je eli warto Ê
zmiennej a bÚdzie mniejsza od warto ci zmiennej b I warto Ê zmiennej a nie bÚdzie
mniejsza od warto ci zmiennej c. Takie instrukcje powinny byÊ grupowane za pomocÈ
nawiasów i mogÈ zawieraÊ wiele ró nych odmian.
    Wiele rzeczy mo emy sprowadziÊ do zmiennych, operatorów porównania i struk-
tur sterujÈcych. W przykïadzie myszy poszukujÈcej po ywienia gïód mo emy przed-
stawiÊ jako zmiennÈ boolowskÈ o warto ci true lub false (prawda lub faïsz). Oczy-
wi cie, 1 oznacza true, a 0 — false.




                                                                  Programowanie   29
While (g ód == 1)
             {
               Szukaj po ywienia;
               Zjedz po ywienie;
             }


                Oto kolejny skrót czÚsto wykorzystywany przez programistów i hakerów. JÚzyk
             C nie zawiera adnych operatorów boolowskich, wiÚc ka da warto Ê niezerowa jest
             uznawana za true, a instrukcja jest szacowana jako false, gdy zawiera 0. W rzeczy-
             wisto ci operatory porównania faktycznie zwracajÈ 1, je eli porównanie jest speï-
             nione, a w przeciwnym przypadku zwracajÈ 0. Sprawdzenie, czy zmienna g ód ma
             warto Ê 1, zwróci 1, je eli g ód ma warto Ê 1, lub zwróci 0, je eli gïód ma warto Ê 0.
             Poniewa program wykorzystuje tylko te dwa przypadki, mo na w ogóle pominÈÊ
             operator porównania.

             While (g ód)
             {
               Szukaj po ywienia;
               Zjedz po ywienie;
             }


                Sprytniejszy program sterujÈcy zachowaniem myszy z u yciem wiÚkszej liczby
             danych wej ciowych to przykïad, jak mo na ïÈczyÊ operatory porównania ze zmien-
             nymi.

             While ((g ód) && !(kot_obecny))
             {
               Szukaj po ywienia;
               If (!(po ywienie_znajduje_siú_w_pu apce_na_myszy;
                 Zjedz po ywienie;
             }


                W tym przykïadzie zaïo ono, e dostÚpne sÈ równie zmienne opisujÈce obec-
             no Ê kota oraz poïo enie po ywienia z warto ciami 1 dla speïnienia warunku i 0 dla
             przypadku przeciwnego. Wystarczy pamiÚtaÊ, e warto Ê niezerowa oznacza prawdÚ,
             a warto Ê 0 jest szacowana jako faïsz.

             0x244       Funkcje
             Czasami zdarzajÈ siÚ zestawy instrukcji, których programista bÚdzie potrzebowaï
             kilka razy. Takie instrukcje mo na zgrupowaÊ w mniejszym podprogramie, zwanym
             funkcjÈ. W innych jÚzykach funkcje nazywane sÈ tak e procedurami i podprocedu-
             rami. Przykïadowo wykonanie skrÚtu samochodem skïada siÚ z kilku mniejszych
             instrukcji: wïÈcz odpowiedni kierunkowskaz, zwolnij, sprawd , czy nie nadje d ajÈ
             inne samochody, skrÚÊ kierownicÚ w odpowiednim kierunku itd. Opis trasy z poczÈt-
             ku tego rozdziaïu zawieraï caïkiem sporo skrÚtów, jednak e wymienianie wszystkich



30   0x200
drobnych instrukcji przy ka dym skrÚcie byïoby mudne (i zmniejszaïoby czytel-
no Ê kodu). W celu zmodyfikowania sposobu dziaïania funkcji mo emy przesyïaÊ do
niej zmienne jako argumenty. W tym przypadku do funkcji jest przesyïany kierunek
skrÚtu.

Function Skrút(zmienna_kierunku)
{
  W æcz zmienna_kierunku kierunkowskaz;
  Zwolnij;
  Sprawd , czy nie nadje d ajæ inne samochody;
  while (nadje d ajæ inne samochody)
  {
    Zatrzymaj siú;
    Obserwuj nadje d ajæce samochody;
  }
  Obróè kierownicú w zmienna_kierunku;
  while (skrút nie jest uko czony)
  {
    if (prúdko è < 8 km/h)
      Przyspiesz;
  }
  Obróè kierownicú do pierwotnego po o enia;
  Wy æcz zmienna_kierunku kierunkowskaz;
}


   Funkcja ta zawiera wszystkie instrukcje konieczne do wykonania skrÚtu. Gdy
program, w którym funkcja taka siÚ znajduje, musi wykonaÊ skrÚt, mo e po prostu
wywoïaÊ tÚ funkcjÚ. Gdy zostaje wywoïana, znajdujÈce siÚ w niej instrukcje sÈ wy-
konywane z przesïanymi argumentami. NastÚpnie wykonywanie programu powraca
do momentu za wywoïaniem funkcji. Do tej funkcji mo na przesïaÊ warto Ê lewo
albo prawo, co spowoduje wykonanie skrÚtu w tym kierunku.
   Domy lnie w jÚzyku C funkcje mogÈ zwracaÊ warto ci do elementu wywoïujÈ-
cego. Dla osób znajÈcych matematykÚ jest to zupeïnie zrozumiaïe. Wyobra my sobie
funkcjÚ obliczajÈcÈ silniÚ — jest oczywiste, e zwraca wynik.
   W jÚzyku C funkcje nie sÈ oznaczane sïowem kluczowym function. Zamiast tego
sÈ deklarowane przez typ danych zwracanej zmiennej. Taki format bardzo przy-
pomina deklaracjÚ zmiennej. Je eli funkcja w zamierzeniu ma zwracaÊ liczbÚ caï-
kowitÈ (mo e to byÊ np. funkcja obliczajÈca silniÚ jakiej liczby x), jej kod mógïby
wyglÈdaÊ nastÚpujÈco:

int factorial(int x)
{
  int i;
  for(i=1; i < x; i++)
    x *= i;
  return x;
}




                                                               Programowanie    31
Funkcja ta jest deklarowana liczbÈ caïkowitÈ, poniewa mno y ka dÈ warto Ê
             od 1 do x i zwraca wynik, który jest liczbÈ caïkowitÈ. Instrukcja return na koñcu
             funkcji przesyïa zawarto Ê zmiennej x i koñczy wykonywanie funkcji. FunkcjÚ obli-
             czajÈcÈ silniÚ mo na wówczas wykorzystaÊ jak ka dÈ zmiennÈ typu integer w gïównej
             czÚ ci ka dego programu, który „wie” o tej funkcji:

             int a=5, b;
             b = factorial(a);


                 Po ukoñczeniu wykonywania tego krótkiego programu zmienna b bÚdzie miaïa
             warto Ê 120, poniewa funkcja factorial() zostanie wywoïana z argumentem 5
             i zwróci 120.
                 Ponadto w jÚzyku C kompilator musi „wiedzieÊ” o funkcji, zanim jej u yje. W tym
             celu mo na po prostu napisaÊ caïÈ funkcjÚ przed pó niejszym wykorzystaniem jej
             w programie lub skorzystaÊ z prototypu funkcji. Prototyp funkcji jest prostym spo-
             sobem poinformowania kompilatora, i powinien spodziewaÊ siÚ funkcji o podanej
             nazwie, zwracajÈcej okre lony typ danych i przyjmujÈcej argumenty o okre lonym
             typie danych. Faktyczny kod funkcji mo na umie ciÊ pod koniec programu, ale mo na
             jÈ wykorzystaÊ w dowolnym miejscu, poniewa kompilator bÚdzie ju wiedziaï o jej
             istnieniu. Przykïadowy prototyp funkcji factorial() mógïby wyglÈdaÊ nastÚpujÈco:

             int factorial(int);


                 Zwykle prototypy funkcji sÈ umieszczane blisko poczÈtku programu. W proto-
             typie nie ma potrzeby definiowania nazw zmiennych, poniewa dzieje siÚ to w sa-
             mej funkcji. Kompilator musi jedynie znaÊ nazwÚ funkcji, typ zwracanych danych
             i typy danych argumentów funkcjonalnych.
                 Je eli funkcja nie posiada warto ci, którÈ mo e zwróciÊ (np. wcze niej opisana
             funkcja skrúè()), powinna byÊ zadeklarowana jako typ void. Jednak e funkcja skrúè()
             nie posiada jeszcze caïej funkcjonalno ci wymaganej przez nasz opis dojazdu. Ka dy
             skrÚt w opisie dojazdu zawiera zarówno kierunek, jak i nazwÚ ulicy. To oznacza, e
             funkcja skrÚcajÈca powinna przyjmowaÊ dwie zmienne: kierunek skrÚtu oraz nazwÚ
             ulicy, w którÈ nale y skrÚciÊ. To komplikuje funkcjÚ skrÚcajÈcÈ, poniewa przed
             wykonaniem skrÚtu nale y zlokalizowaÊ ulicÚ. Bardziej kompletna funkcja skrÚcajÈca,
             w której wykorzystano skïadniÚ podobnÈ do jÚzyka C, jest zamieszczona w pseu-
             dokodzie poni szego listingu.

             void skrúè(zmienna_kierunku, nazwa_docelowej_ulicy)
             {
               Szukaj tabliczki z nazwæ ulicy;
               nazwa_bie æcego_skrzy owania = odczytaj tabliczkú z nazwæ ulicy;
               while (nazwa_bie æcego_skrzy owania != nazwa_docelowej_ulicy)
               {
                 Szukaj innej tabliczki z nazwæ ulicy;
                 nazwa_bie æcego_skrzy owania = odczytaj tabliczkú z nazwæ ulicy;
               }



32   0x200
W æcz zmienna_kierunku kierunkowskaz;
Zwolnij;
Sprawd , czy nie nadje d ajæ inne samochody;
  while (nadje d ajæ inne samochody)
  {
    Zatrzymaj siú;
    Obserwuj nadje d ajæce samochody;
  }
  Obróè kierownicú w zmienna_kierunku;
  while (skrút nie jest uko czony)
  {
    if (prúdko è < 8 km/h)
      Przyspiesz;
  }
  Obróè kierownicú do pierwotnego po o enia;
  Wy æcz zmienna_kierunku kierunkowskaz;
}


    Funkcja ta zawiera sekcjÚ, która wyszukuje odpowiednie skrzy owanie poprzez
odnajdywanie tabliczki z nazwÈ ulicy, odczytywanie z niej nazwy i przechowywanie
jej w zmiennej o nazwie nazwa_bie æcego_skrzy owania. Wyszukiwanie i odczyty-
wanie tabliczek z nazwami odbywa siÚ do momentu odnalezienia docelowej ulicy.
Wówczas wykonywane sÈ pozostaïe instrukcje skrÚtu. Mo emy teraz zmieniÊ pseu-
dokod z instrukcjami dojazdu, aby wykorzystywaï funkcjÚ skrÚtu.

Rozpocznij jazdú na wschód Alejæ Ko ciuszki;
while (po prawej stronie nie ma ko cio a)
{
   Jed Alejæ Ko ciuszki;
}
If (ulica zablokowana)
{
   Skrúè(prawo, ul. Moniuszki);
   Skrúè(lewo, ul. Prusa);
   Skrúè(prawo, ul. Orzeszkowej);
}
else
{
   Skrúè(prawo, ul. Orzeszkowej);
}
Skrúè(lewo, ul. Docelowa);
For (i=0; i<5; i++)
{
   Jed prosto 1 kilometr;
}
Zatrzymaj siú przy ul. Docelowej 743;


   Funkcje nie sÈ czÚsto wykorzystywane w pseudokodzie, bo zwykle jest on sto-
sowany przez programistów do zarysowania zaïo eñ programu przed napisaniem
kompilowalnego kodu. Poniewa pseudokod nie musi dziaïaÊ, nie trzeba wypisywaÊ
peïnych funkcji — wystarczy jedynie krótki zapisek: Tu zrób co zïo onego. Jednak



                                                             Programowanie   33
w jÚzyku programowania, takim jak C, funkcje sÈ czÚsto wykorzystywane. WiÚkszo Ê
             prawdziwej u yteczno ci C pochodzi ze zbiorów istniejÈcych funkcji, zwanych
             bibliotekami.


0x250 Zaczynamy brudziÊ sobie rÚce
             Gdy zaznajomili my siÚ ju trochÚ ze skïadniÈ jÚzyka C i wyja nili my kilka pod-
             stawowych pojÚÊ programistycznych, przej cie do faktycznego programowania w C
             nie jest niczym nadzwyczajnym. Kompilatory jÚzyka C istniejÈ dla niemal ka dego
             systemu operacyjnego i architektury procesora, jednak w niniejszej ksiÈ ce bÚdziemy
             wykorzystywali wyïÈcznie system Linux i procesor z rodziny x86. Linux jest dar-
             mowym systemem operacyjnym, do którego ka dy ma dostÚp, a procesory x86 sÈ
             najpopularniejszymi procesorami konsumenckimi na wiecie. Poniewa hacking
             wiÈ e siÚ gïównie z eksperymentowaniem, najlepiej bÚdzie, je eli w trakcie lektury
             bÚdziesz dysponowaï kompilatorem jÚzyka C.
                 DziÚki dyskowi LiveCD doïÈczonemu do niniejszej ksiÈ ki mo esz praktycznie
             stosowaÊ przekazywane informacje, je eli tylko dysponujesz procesorem z rodziny
             x86. Wystarczy wïo yÊ dysk CD do napÚdu i ponownie uruchomiÊ komputer. Uru-
             chomione zostanie rodowisko linuksowe, które nie narusza istniejÈcego systemu ope-
             racyjnego. W tym rodowisku mo esz wypróbowywaÊ przykïady z ksiÈ ki, a tak e
             przeprowadzaÊ wïasne eksperymenty.
                 Przejd my do rzeczy. Program firstprog.c jest prostym fragmentem kodu w C,
             wypisujÈcym 10 razy „Hello world!”.

             Listing 2.1. firstprog.c
             #include <stdio.h>

             int main()
             {
               int i;
               for(i=0; i < 10; i++) // Wykonaj pútlú 10 razy.
               {
                 puts("Hello, world!n"); // Przeka   a cuch do wyj cia.
               }
               return 0; // Poinformuj OS, e program zako czy siú bez b údów.
             }


                  Gïówne wykonywanie programu napisanego w C rozpoczyna siÚ w funkcji main().
             Tekst znajdujÈcy siÚ za dwoma uko nikami jest komentarzem ignorowanym przez
             kompilator.
                  Pierwszy wiersz mo e wprawiaÊ w zakïopotanie, ale jest to jedynie skïadnia
             informujÈca kompilator, aby doïÈczyï nagïówki dla standardowej biblioteki wej-
               cia-wyj cia o nazwie stdio. Ten plik nagïówkowy jest dodawany do programu
             podczas kompilacji. Znajduje siÚ on w /usr/include/stdio.h i definiuje kilka staïych
             i prototypów funkcji dla odpowiednich funkcji w standardowej bibliotece we-wy.
             Poniewa funkcja main() wykorzystuje funkcjÚ printf() ze standardowej biblioteki


34   0x200
we-wy, wymagany jest prototyp funkcji printf() przed jej zastosowaniem. Ten
prototyp funkcji (a tak e wiele innych) znajduje siÚ w pliku nagïówkowym stdio.h.
Sporo mo liwo ci jÚzyka C to pochodne jego zdolno ci do rozbudowy oraz wyko-
rzystania bibliotek. Reszta kodu powinna byÊ zrozumiaïa i przypomina wcze niej
prezentowany pseudokod. SÈ nawet nawiasy klamrowe, które mo na byïo pominÈÊ.
To, co bÚdzie siÚ dziaïo po uruchomieniu tego programu, powinno byÊ oczywiste,
ale skompilujmy go za pomocÈ GCC, aby siÚ upewniÊ.
    GNU Compiler Collection jest darmowym kompilatorem jÚzyka C, tïumaczÈcym
jÚzyk C na jÚzyk maszynowy, zrozumiaïy dla komputera. W wyniku tïumaczenia
powstaje wykonywalny plik binarny, któremu domy lnie nadawana jest nazwa a.out.
Czy skompilowany program wykonuje to, co chcieli my?

reader@hacking:~/booksrc $   gcc firstprog.c
reader@hacking:~/booksrc $   ls -l a.out
-rwxr-xr-x 1 reader reader   6621 2007-09-06 22:16 a.out
reader@hacking:~/booksrc $   ./a.out
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
reader@hacking:~/booksrc $



0x251       WiÚkszy obraz
Dobrze, tego wszystkiego mo na siÚ nauczyÊ na podstawowym kursie programo-
wania — sÈ to podstawy, ale niezbÚdne. WiÚkszo Ê poczÈtkowych kursów progra-
mowania uczy jedynie, jak czytaÊ i pisaÊ w jÚzyku C. ProszÚ mnie le nie zrozumieÊ
— pïynna znajomo Ê C jest bardzo przydatna i wystarczy do stania siÚ dobrym
programistÈ, ale jest to tylko czÚ Ê wiÚkszej caïo ci. WiÚkszo Ê programistów uczy
siÚ jÚzyka z góry do doïu i nigdy nie ma szerszego obrazu. Hakerzy sÈ tak dobrzy,
poniewa wiedzÈ, jak wszystkie czÚ ci tego wiÚkszego obrazu wchodzÈ ze sobÈ
w interakcje. Aby w programowaniu patrzeÊ szerzej, wystarczy sobie zdaÊ sprawÚ, e
kod w jÚzyku C bÚdzie kompilowany. Kod nie mo e nic zrobiÊ, dopóki nie zostanie
skompilowany do wykonywalnego pliku binarnego. My lenie o kodzie ródïowym
w C jak o programie jest czÚstym bïÚdem wykorzystywanym codziennie przez ha-
kerów. Instrukcje w pliku a.out sÈ zapisane w jÚzyku maszynowym — podstawowym
jÚzyku zrozumiaïym dla procesora. Kompilatory tïumaczÈ jÚzyk kodu C na jÚzyk
maszynowy ró nych architektur procesorów. W tym przypadku procesor pocho-
dzi z rodziny wykorzystujÈcej architekturÚ x86. IstniejÈ równie architektury pro-
cesorów Sparc (u ywane w stacjach roboczych Sun) oraz architektura PowerPC



                                                               Programowanie   35
(wykorzystywana w macintoshach przed zastosowaniem procesorów Intela). Ka da
             architektura wymaga innego jÚzyka maszynowego, wiÚc kompilator jest po redni-
             kiem — tïumaczy kod w jÚzyku C na jÚzyk maszynowy docelowej architektury.
                 Dopóki skompilowany program dziaïa, przeciÚtny programista skupia siÚ wy-
             ïÈcznie na kodzie ródïowym. Jednak haker zdaje sobie sprawÚ, e w rzeczywisto ci
             wykonywany jest program skompilowany. MajÈc dogïÚbnÈ wiedzÚ na temat dziaïania
             procesora, haker mo e manipulowaÊ dziaïajÈcymi programami. Widzieli my kod
              ródïowy naszego pierwszego programu i skompilowali my go do pliku wykony-
             walnego dla architektury x86. Ale jak wyglÈda ten wykonywalny plik binarny? Na-
             rzÚdzia programistyczne GNU zawierajÈ program o nazwie objdump, który mo e byÊ
             u yty do badania skompilowanych plików binarnych. Rozpocznijmy od poznania
             kodu maszynowego, na który zostaïa przetïumaczona funkcja main().

             reader@hacking:~/booksrc $ objdump -D a.out | grep -A20 main.:
             08048374 <main>:
             8048374: 55 push %ebp
             8048375: 89 e5 mov %esp,%ebp
             8048377: 83 ec 08 sub $0x8,%esp
             804837a: 83 e4 f0 and $0xfffffff0,%esp
             804837d: b8 00 00 00 00 mov $0x0,%eax
             8048382: 29 c4 sub %eax,%esp
             8048384: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp)
             804838b: 83 7d fc 09 cmpl $0x9,0xfffffffc(%ebp)
             804838f: 7e 02 jle 8048393 <main+0x1f>
             8048391: eb 13 jmp 80483a6 <main+0x32>
             8048393: c7 04 24 84 84 04 08 movl $0x8048484,(%esp)
             804839a: e8 01 ff ff ff call 80482a0 <printf@plt>
             804839f: 8d 45 fc lea 0xfffffffc(%ebp),%eax
             80483a2: ff 00 incl (%eax)
             80483a4: eb e5 jmp 804838b <main+0x17>
             80483a6: c9 leave
             80483a7: c3 ret
             80483a8: 90 nop
             80483a9: 90 nop
             80483aa: 90 nop
             reader@hacking:~/booksrc $


                 Program objdump zwróciï zbyt wiele wierszy wynikowych, aby rozsÈdnie siÚ im
             przyjrzeÊ, wiÚc przekazali my wyj cie do grep z opcjÈ powodujÈcÈ wy wietlenie
             tylko 20 wierszy za wyra eniem regularnym main.:. Ka dy bajt jest reprezentowany
             w notacji szesnastkowej, systemie liczbowym o podstawie 16. System liczbowy, do
             którego jeste my najbardziej przyzwyczajeni, wykorzystuje podstawÚ 10, a przy
             liczbie 10 nale y umie ciÊ dodatkowy symbol. W systemie szesnastkowym stoso-
             wane sÈ cyfry od 0 do 9 reprezentujÈce 0 do 9, ale tak e litery A do F, które repre-
             zentujÈ w nim liczby od 10 do 15. Jest to wygodny zapis, poniewa bajt zawiera 8 bi-
             tów, z których ka dy mo e mieÊ warto Ê prawda lub faïsz. To oznacza, e bajt ma
             256 (28) mo liwych warto ci, wiÚc ka dy bajt mo e byÊ opisany za pomocÈ dwóch
             cyfr w systemie szesnastkowym.



36   0x200
Liczby szesnastkowe — rozpoczynajÈc od 0x8048374 po lewej stronie — sÈ ad-
resami pamiÚci. Bity jÚzyka maszynowego muszÈ byÊ gdzie przechowywane, a tym
„gdzie ” jest pamiÚÊ. PamiÚÊ jest po prostu zbiorem bajtów z tymczasowej przestrzeni
magazynowej, którym przypisano adresy liczbowe.
    Podobnie jak rzÈd domów przy lokalnej ulicy, z których ka dy posiada wïasny
adres, pamiÚÊ mo emy traktowaÊ jako rzÈd bajtów, z których ka dy ma wïasny adres.
Do ka dego bajta pamiÚci mo na uzyskaÊ dostÚp za pomocÈ jego adresu, a w tym
przypadku procesor siÚga do tej czÚ ci pamiÚci, aby pobraÊ instrukcje jÚzyka ma-
szynowego skïadajÈce siÚ na skompilowany program. Starsze procesory Intela z rodzi-
ny x86 wykorzystujÈ 32-bitowy schemat adresacji, natomiast nowsze — 64-bitowy.
Procesory 32-bitowe posiadajÈ 232 (lub te 4 294 967 296) mo liwych adresów, na-
tomiast procesory 64-bitowe dysponujÈ ilo ciÈ adresów równÈ 264 (1,84467441 × 1019).
Procesory 64-bitowe mogÈ pracowaÊ w trybie kompatybilno ci 32-bitowej, co umo -
liwia im szybkie wykonywanie kodu 32-bitowego.
    Bajty szesnastkowe znajdujÈce siÚ po rodku powy szego listingu sÈ instrukcjami
w jÚzyku maszynowym procesora x86. Oczywi cie, te warto ci szesnastkowe sÈ
jedynie reprezentacjami binarnych jedynek i zer, które rozumie procesor. Ale po-
niewa 0101010110001001111001011000001111101100111100001… przydaje siÚ
tylko procesorowi, kod maszynowy jest wy wietlany jako bajty szesnastkowe, a ka da
instrukcja jest umieszczana w osobnym wierszu, co przypomina podziaï akapitu
na zdania.
    Gdy siÚ zastanowimy, oka e siÚ, e bajty szesnastkowe same w sobie te nie sÈ
przydatne — tutaj dochodzi do gïosu jÚzyk asembler. Instrukcje po prawej stronie
sÈ zapisane w asemblerze. Asembler jest po prostu zbiorem mnemoników dla od-
powiednich instrukcji jÚzyka maszynowego. Instrukcja ret jest znacznie ïatwiejsza
do zapamiÚtania i zrozumienia ni 0xc3 czy te 11000011. W przeciwieñstwie do C
i innych jÚzyków kompilowanych, instrukcje asemblera wystÚpujÈ w relacji jeden-
do-jednego z instrukcjami odpowiednimi jÚzyka maszynowego. Oznacza to, e skoro
ka da architektura procesora posiada wïasny zestaw instrukcji jÚzyka maszynowego,
ka da z nich ma równie wïasnÈ odmianÚ asemblera. JÚzyk asemblera jest dla pro-
gramistów tylko sposobem reprezentacji instrukcji jÚzyka maszynowego podawa-
nych procesorowi. Dokïadny sposób reprezentacji tych instrukcji maszynowych jest
tylko kwestiÈ konwencji i preferencji. ChoÊ teoretycznie mo na stworzyÊ wïasnÈ
skïadniÚ asemblera dla architektury x86, wiÚkszo Ê osób wykorzystuje jeden z gïów-
nych typów — skïadniÚ AT&T lub Intel. Kod asemblera przedstawiony na stronie 21
jest zgodny ze skïadniÈ AT&T, poniewa niemal wszystkie dezasemblery w Linuksie
domy lnie wykorzystujÈ tÚ skïadniÚ. SkïadniÚ AT&T mo na ïatwo rozpoznaÊ dziÚ-
ki kakofonii symboli % i $ umieszczanych przed wszystkimi elementami (proszÚ
ponownie spojrzeÊ na stronÚ 21). Ten sam kod mo na wy wietliÊ w skïadni Intela,
dodajÈc do polecenia objdump dodatkowÈ opcjÚ -M:

reader@hacking:~/booksrc $ objdump -M intel -D a.out | grep -A20 main.:
08048374 <main>:
8048374: 55 push ebp
8048375: 89 e5 mov ebp,esp



                                                                 Programowanie   37
8048377: 83 ec 08 sub esp,0x8
             804837a: 83 e4 f0 and esp,0xfffffff0
             804837d: b8 00 00 00 00 mov eax,0x0
             8048382: 29 c4 sub esp,eax
             8048384: c7 45 fc 00 00 00 00 mov DWORD PTR [ebp-4],0x0
             804838b: 83 7d fc 09 cmp DWORD PTR [ebp-4],0x9
             804838f: 7e 02 jle 8048393 <main+0x1f>
             8048391: eb 13 jmp 80483a6 <main+0x32>
             8048393: c7 04 24 84 84 04 08 mov DWORD PTR [esp],0x8048484
             804839a: e8 01 ff ff ff call 80482a0 <printf@plt>
             804839f: 8d 45 fc lea eax,[ebp-4]
             80483a2: ff 00 inc DWORD PTR [eax]
             80483a4: eb e5 jmp 804838b <main+0x17>
             80483a6: c9 leave
             80483a7: c3 ret
             80483a8: 90 nop
             80483a9: 90 nop
             80483aa: 90 nop
             reader@hacking:~/booksrc $


                  Uwa am, e skïadnia Intela jest znacznie bardziej czytelna i ïatwiejsza do zro-
             zumienia, wiÚc bÚdzie ona stosowana w niniejszej ksiÈ ce. Niezale nie od repre-
             zentacji jÚzyka asemblera, polecenia rozumiane przez procesor sÈ caïkiem proste.
             Instrukcje te skïadajÈ siÚ z operacji i czasem dodatkowych operacji opisujÈcych cel
             i (lub) ródïo operacji. Operacje te przenoszÈ dane w pamiÚci, aby wykonaÊ jakie-
             go rodzaju podstawowe dziaïania matematyczne, lub przerywajÈ dziaïanie proce-
             sora, by wykonaÊ co innego. To jest wszystko, co procesor potrafi wykonaÊ. Jednak,
             podobnie jak za pomocÈ stosunkowo niewielkiego alfabetu napisano miliony ksiÈ ek,
             tak samo, korzystajÈc z niewielkiego zbioru instrukcji maszynowych, mo na utworzyÊ
             nieskoñczenie wiele programów.
                  Procesory posiadajÈ równie wïasny zestaw specjalnych zmiennych zwanych
             rejestrami. WiÚkszo Ê instrukcji wykorzystuje rejestry do odczytywania lub zapi-
             sywania danych, wiÚc ich poznanie jest niezbÚdne do zrozumienia instrukcji. Du y
             obraz wciÈ siÚ powiÚksza…

             0x252       Procesor x86
             Procesor 8086 byï pierwszym procesorem w architekturze x86. Zostaï opracowany
             i wyprodukowany przez firmÚ Intel, która pó niej wprowadzaïa na rynek bardziej
             zaawansowane procesory z tej rodziny: 80186, 80286m 80386 i 80486. Je eli pamiÚ-
             tasz, e w latach 80. i 90. ubiegïego wieku mówiono o procesorach 386 i 486, chodziïo
             wówczas o te wïa nie ukïady.
                 Procesor x86 posiada kilka rejestrów, które sÈ dla niego czym w rodzaju we-
             wnÚtrznych zmiennych. Mógïbym teraz przeprowadziÊ abstrakcyjny wykïad na temat
             rejestrów, ale uwa am, e lepiej zobaczyÊ co na wïasne oczy. NarzÚdzia progra-
             mistyczne GNU zawierajÈ równie debuger o nazwie GDB. Debugery sÈ u ywane
             przez programistów do wykonywania skompilowanych programów krok po kroku,
             badania pamiÚci programu i przeglÈdania rejestrów procesora. Programista, który



38   0x200
nigdy nie korzystaï z debugera do przyjrzenia siÚ wewnÚtrznym mechanizmom
pracy programu, jest jak siedemnastowieczny badacz, który nigdy nie u ywaï mi-
kroskopu. Debuger, tak jak mikroskop, pozwala hakerowi na precyzyjne przyjrze-
nie siÚ kodowi maszynowemu, ale mo liwo ci debugera wykraczajÈ daleko poza tÚ
metaforÚ. W przeciwieñstwie do mikroskopu, debuger umo liwia obejrzenie wy-
konywania programu ze wszystkich stron, wstrzymanie go oraz zmianÚ wszelkich
parametrów.
   Poni ej GDB zostaï u yty do wy wietlenia stanu rejestrów procesora tu przed
rozpoczÚciem programu:

reader@hacking:~/booksrc $ gdb -q ./a.out
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) break main

Breakpoint 1 at 0x804837a
(gdb) run
Starting program: /home/reader/booksrc/a.out

Breakpoint 1, 0x0804837a in main ()
(gdb) info registers
eax 0xbffff894 -1073743724
ecx 0x48e0fe81 1222704769
edx 0x1 1
ebx 0xb7fd6ff4 -1208127500
esp 0xbffff800 0xbffff800
ebp 0xbffff808 0xbffff808
esi 0xb8000ce0 -1207956256
edi 0x0 0
eip 0x804837a 0x804837a <main+6>
eflags 0x286 [ PF SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) quit
The program is running. Exit anyway? (y or n) y
reader@hacking:~/booksrc $


    Punkt wstrzymania zostaï ustawiony przy funkcji main(), wiÚc wykonywanie
programu zostanie zatrzymane tu przed uruchomieniem naszego kodu. NastÚpnie
GDB uruchamia program, zatrzymuje siÚ w punkcie wstrzymania i wy wietla wszyst-
kie rejestry procesora i ich bie Ècy stan.
    Pierwsze cztery rejestry (EAX, ECX, EDX i EBX) sÈ rejestrami ogólnego prze-
znaczenia. SÈ to odpowiednio rejestry: akumulatorowy, licznika, danych i bazowy.
SÈ one wykorzystywane do ró nych celów, ale sïu È gïównie jako zmienne tymcza-
sowe dla procesora, gdy wykonuje instrukcje kodu maszynowego.




                                                                 Programowanie   39
Kolejne cztery rejestry (ESP, EBP, ESI i EDI) sÈ równie rejestrami ogólnego
             przeznaczenia, ale czasem nazywa siÚ je wska nikami i indeksami. SÈ to odpowiednio:
             wska nik, wska nik bazowy, ródïo i przeznaczenie. Pierwsze dwa rejestry sÈ nazy-
             wane wska nikami, poniewa przechowujÈ 32-bitowe adresy, wskazujÈce do miejsc
             w pamiÚci. Te rejestry sÈ istotne dla wykonywania programu i zarzÈdzania pamiÚciÈ.
             Pó niej omówiÚ je dokïadniej. Kolejne dwa rejestry, z technicznego punktu widzenia
             równie wska nikowe, czÚsto wykorzystywane sÈ do wskazywania ródïa i celu, gdy
             dane muszÈ byÊ odczytane lub zapisane. IstniejÈ instrukcje odczytujÈce i zapisujÈce,
             które u ywajÈ tych rejestrów, ale przewa nie mo na je traktowaÊ jak zwykïe rejestry
             ogólnego przeznaczenia.
                Rejestr EIP jest rejestrem wska nika instrukcji, wskazujÈcym aktualnie wykony-
             wanÈ instrukcjÚ. Tak jak dziecko podczas czytania pokazuje sobie palcem poszczegól-
             ne sïowa, tak procesor odczytuje konkretne instrukcje, korzystajÈc z EIP jak z palca.
             Oczywi cie, rejestr ten jest bardzo istotny i bÚdzie czÚsto wykorzystywany podczas
             debugowania. Aktualnie wskazuje adres pamiÚci 0x804838a.
                Pozostaïy rejestr, EFLAGS, zawiera kilka flag bitowych wykorzystywanych do
             porównañ oraz segmentacji pamiÚci. PamiÚÊ jest dzielona na kilka ró nych seg-
             mentów, co opiszÚ pó niej, a rejestr ten pozwala je ledziÊ. Przewa nie mo emy je
             zignorowaÊ, poniewa rzadko konieczny jest bezpo redni dostÚp do nich.

             0x253       JÚzyk asembler
             Poniewa w niniejszej ksiÈ ce wykorzystujemy skïadniÚ Intela w jÚzyku asembler,
             musimy odpowiednio skonfigurowaÊ narzÚdzia. W GDB skïadniÚ dezasemblera
             mo na ustawiÊ na intelowskÈ, wpisujÈc po prostu set disassembly intel lub w skrócie
             set dis intel. Mo emy skonfigurowaÊ GDB tak, aby to ustawienie byïo aktywne
             przy ka dym uruchomieniu, umieszczajÈc to polecenie w pliku .gdbinit w katalogu
             domowym.

             reader@hacking:~/booksrc   $ gdb -q
             (gdb) set dis intel
             (gdb) quit
             reader@hacking:~/booksrc   $ echo "set dis intel" > ~/.gdbinit
             reader@hacking:~/booksrc   $ cat ~/.gdbinit
             set dis intel
             reader@hacking:~/booksrc   $


                 Po skonfigurowaniu GDB tak, eby wykorzystywaï skïadniÚ Intela, zapoznajmy
             siÚ z niÈ. W skïadni Intela instrukcje asemblera majÈ zwykle poni szÈ postaÊ:
             operacja <cel>, < ród o>
                 Warto ciami docelowymi i ródïowymi sÈ rejestr, adres pamiÚci lub warto Ê.
             Operacje sÈ zwykle intuicyjnie rozumianymi mnemonikami. Operacja mov przenosi
             warto Ê ze ródïa do celu, sub odejmuje, inc inkrementuje itd. Przykïadowo poni sze
             instrukcje przenoszÈ warto Ê z ESP do EBP, a nastÚpnie odejmujÈ 8 od ESP (zapisu-
             jÈc wynik w ESP).




40   0x200
8048375: 89 e5 mov ebp,esp
8048377: 83 ec 08 sub esp,0x8


    DostÚpne sÈ równie operacje wykorzystywane do sterowanie przebiegiem
wykonywania. Operacja cmp sïu y do porównywania warto ci, a niemal wszystkie
operacje, których nazwa rozpoczyna siÚ literÈ j, sïu È do przeskakiwania do innej
czÚ ci kodu (w zale no ci od wyniku porównania). W poni szym przykïadzie najpierw
4-bajtowa warto Ê znajdujÈca w ERB minus 4 jest porównywana z liczbÈ 9. NastÚpna
instrukcja jest skrótem od przeskocz, je eli mniejsze lub równe ni (ang. jump if less
than or equal to), odnoszÈcym siÚ do wyniku wcze niejszego porównania. Je eli
warto Ê ta jest mniejsza lub równa 9, wykonywanie przeskoczy do instrukcji znaj-
dujÈcej siÚ pod adresem 0x8048393. W przeciwnym przypadku wykonywana bÚdzie
kolejna instrukcja z bezwarunkowym przeskokiem. Je eli warto Ê nie bÚdzie mniejsza
ani równa 9, procesor przeskoczy do 0x80483a6.

804838b: 83 7d fc 09 cmp DWORD PTR [ebp-4],0x9
804838f: 7e 02 jle 8048393 <main+0x1f>
8048391: eb 13 jmp 80483a6 <main+0x32>


   Przykïady te pochodzÈ z naszej poprzedniej dezasemblacji. Skonfigurowali my
debuger do wykorzystywania skïadni Intela, wiÚc wykorzystajmy go do kroczenia
przez nasz pierwszy program na poziomie instrukcji asemblera.
   W kompilatorze GCC mo na podaÊ opcjÚ –g, dziÚki czemu zostanÈ doïÈczone
dodatkowe informacje debugowania, co da GDB dostÚp do kodu ródïowego.

reader@hacking:~/booksrc $ gcc -g firstprog.c
reader@hacking:~/booksrc $ ls -l a.out
-rwxr-xr-x 1 matrix users 11977 Jul 4 17:29 a.out
reader@hacking:~/booksrc $ gdb -q ./a.out
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) list
1 #include <stdio.h>
2
3 int main()
4 {
5 int i;
6 for(i=0; i < 10; i++)
7 {
8 printf("Hello, world!n");
9 }
10 }
(gdb) disassemble main
Dump of assembler code for function main():
0x08048384 <main+0>: push ebp
0x08048385 <main+1>: mov ebp,esp
0x08048387 <main+3>: sub esp,0x8
0x0804838a <main+6>: and esp,0xfffffff0
0x0804838d <main+9>: mov eax,0x0
0x08048392 <main+14>: sub esp,eax




                                                                 Programowanie    41
0x08048394 <main+16>: mov DWORD PTR [ebp-4],0x0
             0x0804839b <main+23>: cmp DWORD PTR [ebp-4],0x9
             0x0804839f <main+27>: jle 0x80483a3 <main+31>
             0x080483a1 <main+29>: jmp 0x80483b6 <main+50>
             0x080483a3 <main+31>: mov DWORD PTR [esp],0x80484d4
             0x080483aa <main+38>: call 0x80482a8 <_init+56>
             0x080483af <main+43>: lea eax,[ebp-4]
             0x080483b2 <main+46>: inc DWORD PTR [eax]
             0x080483b4 <main+48>: jmp 0x804839b <main+23>
             0x080483b6 <main+50>: leave
             0x080483b7 <main+51>: ret
             End of assembler dump.
             (gdb) break main
             Breakpoint 1 at 0x8048394: file firstprog.c, line 6.
             (gdb) run
             Starting program: /hacking/a.out

             Breakpoint 1, main() at firstprog.c:6
             6 for(i=0; i < 10; i++)
             (gdb) info register eip
             eip 0x8048394 0x8048394
             (gdb)


                 Najpierw wypisywany jest kod ródïowy oraz dezasemblacja funkcji main().
             NastÚpnie na poczÈtku main() ustawiany jest punkt wstrzymania i program jest
             uruchamiany. Ten punkt wstrzymania po prostu informuje debuger, aby wstrzymaï
             wykonywanie programu, gdy dojdzie do tego punktu. Poniewa punkt wstrzymania
             zostaï ustawiony na poczÈtku funkcji main(), program dociera do punktu wstrzy-
             mania i zatrzymuje siÚ przed wykonaniem jakichkolwiek instrukcji z funkcji main().
             NastÚpnie wy wietlana jest warto Ê EIP (wska nika instrukcji).
                 Nale y zwróciÊ uwagÚ, e EIP zawiera adres pamiÚci, wskazujÈcy instrukcjÚ
             w dezasemblacji funkcji main() (pogrubionej na listingu). Wcze niejsze instrukcje
             (zapisane kursywÈ), razem nazywane prologiem funkcji, sÈ generowane przez kom-
             pilator w celu ustawienia pamiÚci dla reszty zmiennych lokalnych funkcji main().
             Jednym z powodów konieczno ci deklaracji zmiennych w jÚzyku C jest pomoc
             w konstrukcji tej czÚ ci kodu. Debuger „wie”, e ta czÚ Ê kodu jest generowana
             automatycznie i potrafi jÈ pominÈÊ. Prologiem funkcji zajmiemy siÚ pó niej, a na
             razie, wzorujÈc siÚ na GDB, pominiemy go.
                 Debuger GDB zawiera bezpo redniÈ metodÚ badania pamiÚci za pomocÈ pole-
             cenia x, które jest skrótem od examine. Badanie pamiÚci jest bardzo wa nÈ umiejÚtno-
              ciÈ ka dego hakera. WiÚkszo Ê technik hakerskich przypomina sztuczki magiczne
             — wydajÈ siÚ niesamowite i magiczne, dopóki nie poznasz oszustwa. Zarówno
             w magii, jak i hakerstwie, je eli popatrzymy w odpowiednie miejsce, sztuczka stanie
             siÚ oczywista. Jest to jeden z powodów, dla których dobry magik nigdy nie wykonuje
             dwa razy tego samego triku w czasie jednego wystÚpu. Jednak za pomocÈ debugera,
             takiego jak GDB, mo emy dokïadnie zbadaÊ ka dy aspekt wykonywania programu,
             wstrzymaÊ go, przej Ê krok dalej i powtórzyÊ tyle razy, ile potrzeba. Poniewa
             dziaïajÈcy program to w wiÚkszo ci procesor i segmenty pamiÚci, zbadanie pamiÚci
             jest pierwszÈ z metod przekonania siÚ, co naprawdÚ siÚ dzieje.


42   0x200
Polecenie examine w GDB mo e zostaÊ u yte do przyjrzenia siÚ okre lonym adre-
              som pamiÚci na ró ne sposoby. To polecenie oczekuje dwóch argumentów: miejsca
              w pamiÚci, które ma byÊ zbadane, oraz okre lenia sposobu wy wietlania zawarto ci.
                  Do okre lania formatu wy wietlania równie u ywany jest jednoliterowy skrót,
              który mo na poprzedziÊ liczbÈ elementów do zbadania. NajczÚ ciej wykorzystywane
              sÈ poni sze skróty formatujÈce:
                  o — wy wietla w formacie ósemkowym,
                  x — wy wietla w formacie szesnastkowym,
                  u — wy wietla w standardowym systemie dziesiÚtnym, bez znaków,
                  t — wy wietla w formacie binarnym.

                 Liter tych mo na u yÊ z poleceniem examine do zbadania okre lonego adresu
              pamiÚci. W poni szym przykïadzie wykorzystano bie Ècy adres z rejestru EIP.
              Skrócone polecenia sÈ czÚsto wykorzystywane w GDB i nawet info register eip
              mo na skróciÊ do i r eip.

(gdb) i r   eip
eip           0x8048384            0x8048384 <main+16>
(gdb) x/o   0x8048384
0x8048384   <main+16>:       077042707
(gdb) x/x   $eip
0x8048384   <main+16>:       0x00fc45c7
(gdb) x/u   $eip
0x8048384   <main+16>:       16532935
(gdb) x/t   $eip
0x8048384   <main+16>:       00000000111111000100010111000111
(gdb)


                  PamiÚÊ, którÈ wskazuje rejestr EIP, mo e byÊ zbadana za pomocÈ adresu prze-
              chowywanego w EIP. Debuger umo liwia bezpo rednie odwoïywanie siÚ do reje-
              strów, wiÚc $eip jest równowa ne warto ci przechowywanej aktualnie w EIP. Warto Ê
              077042707 w systemie ósemkowym jest tym samym, co 0x00fc45c7 w systemie szes-
              nastkowym, co jest tym samym, co 16532935 w systemie dziesiÚtnym, co z kolei jest
              tym samym, co 00000000111111000100010111000111 w systemie dwójkowym.
              Format polecenia examine mo na równie poprzedziÊ cyfrÈ, okre lajÈcÈ liczbÚ
              badanych jednostek w docelowym adresie.

(gdb) x/2x $eip
0x8048384 <main+16>:      0x00fc45c7 0x83000000
(gdb) x/12x $eip
0x8048384 <main+16>:      0x00fc45c7 0x83000000 0x7e09fc7d 0xc713eb02
0x8048394 <main+32>:      0x84842404 0x01e80804 0x8dffffff 0x00fffc45
0x80483a4 <main+48>:      0xc3c9e5eb 0x90909090 0x90909090 0x5de58955
(gdb)




                                                                            Programowanie   43
Domy lnym rozmiarem jednej jednostki jest 4-bajtowa jednostka zwana sïowem.
             Rozmiar jednostek wy wietlania dla polecenia examine mo e byÊ zmieniany poprzez
             dodanie odpowiedniej litery za literÈ formatujÈcÈ. Poprawnymi literami rozmiaru sÈ:
                b — pojedynczy bajt,
                h — póïsïowo o rozmiarze dwóch bajtów,
                w — sïowo o rozmiarze czterech bajtów,
                g — sïowo podwójne o rozmiarze o miu bajtów.
                 Wprowadza to pewien zamÚt, poniewa czasami termin sïowo okre la równie
             warto ci 2-bajtowe. W takim przypadku podwójne sïowo lub DWORD oznacza war-
             to Ê 4-bajtowÈ. W ksiÈ ce tej terminy „sïowo” i DWORD bÚdÈ okre laïy warto ci
             4-bajtowe. Do okre lania warto ci 2-bajtowych bÚdzie u ywany termin „póïsïowo”.
             Poni sze wyj cie z GDB obrazuje pamiÚÊ wy wietlanÈ w ró nych rozmiarach.

(gdb) x/8xb $eip
0x8048384 <main+16>:   0xc7   0x45   0xfc   0x00    0x00       0x00   0x00   0x83
(gdb) x/8xh $eip
0x8048384 <main+16>:   0x45c7 0x00fc 0x0000 0x8300 0xfc7d 0x7e09 0xeb02 0xc713
(gdb) x/8xw $eip
0x8048384 <main+16>:   0x00fc45c7    0x83000000     0x7e09fc7d        0xc713eb02
0x8048394 <main+32>:   0x84842404    0x01e80804     0x8dffffff        0x00fffc45
(gdb)


                  Je eli dobrze siÚ przyjrzysz, zauwa ysz w powy szych danych co dziwnego.
             Pierwsze polecenie examine pokazuje pierwsze osiem bajtów i, oczywi cie, polece-
             nia examine wykorzystujÈce wiÚksze jednostki wy wietlajÈ wiÚcej danych. Jednak e
             wynik pierwszego polecenia pokazuje, e pierwszymi dwoma bajtami sÈ 0xc7 i 0x45,
             ale gdy badane jest póïsïowo w dokïadnie tym samym adresie pamiÚci, pokazywana
             jest warto Ê 0x45c7, czyli bajty sÈ odwrócone. Ten sam efekt mo emy zauwa yÊ
             w przypadku peïnego 4-bajtowego sïowa wy wietlanego jako 0x00fc45c7. Je eli
             jednak pierwsze cztery bajty sÈ wy wietlane bajt po bajcie majÈ one kolejno Ê 0xc7,
             0x45m 0xfc i 0x00.
                  Jest tak, poniewa w procesorze x86 warto ci sÈ przechowywane w kolejno ci
             little endian, co oznacza, e najmniej istotny bajt jest przechowywany jako pierwszy.
             Je eli np. cztery bajty majÈ byÊ interpretowane jako jedna warto Ê, bajty muszÈ byÊ
             u yte w odwrotnej kolejno ci. Debuger GDB jest na tyle mÈdry, e wie, jak prze-
             chowywane sÈ warto ci, wiÚc gdy badane jest sïowo lub póïsïowo, bajty muszÈ byÊ
             odwrócone w celu wy wietlenia poprawnych warto ci w ukïadzie szesnastkowym.
             Przejrzenie tych wy wietlanych warto ci w systemie szesnastkowym i jako liczb
             dziesiÚtnych bez znaku mo e uïatwiÊ zrozumienie tej kwestii.

             (gdb) x/4xb $eip
             0x8048384 <main+16>:    0xc7   0x45   0xfc    0x00
             (gdb) x/4ub $eip
             0x8048384 <main+16>:    199    69     252     0
             (gdb) x/1xw $eip



44   0x200
0x8048384 <main+16>:   0x00fc45c7
(gdb) x/1uw $eip
0x8048384 <main+16>:   16532935
(gdb) quit
The program is running. Exit anyway? (y or n) y
reader@hacking:~/booksrc $ bc -ql
199*(256^3) + 69*(256^2) + 252*(256^1) + 0*(256^0)
3343252480
0*(256^3) + 252*(256^2) + 69*(256^1) + 199*(256^0)
16532935
quit
reader@hacking:~/booksrc $


    Pierwsze cztery bajty sÈ pokazane zarówno w notacji szesnastkowej, jak i standar-
dowej, dziesiÚtnej. Kalkulator dziaïajÈcy w wierszu poleceñ bc posïu yï do wyka-
zania, e je eli bajty zostanÈ zinterpretowane w nieprawidïowej kolejno ci, otrzy-
mamy w wyniku zupeïnie nieprawidïowÈ warto Ê 3343252480. Kolejno Ê bajtów
w danej architekturze jest istotnym czynnikiem, którego nale y byÊ wiadomym.
ChoÊ wiÚkszo Ê narzÚdzi debugujÈcych i kompilatorów zajmuje siÚ automatycznie
szczegóïami zwiÈzanymi z kolejno ciÈ bajtów, czasem bÚdziesz musiaï samodzielnie
manipulowaÊ pamiÚciÈ.
    Oprócz konwersji kolejno ci bajtów, GDB mo e za pomocÈ polecenia examine
wykonywaÊ inne konwersje. Widzieli my ju , e GDB mo e dezasemblowaÊ instruk-
cje jÚzyka maszynowego na zrozumiaïe dla czïowieka instrukcje asemblera. Pole-
cenie examine przyjmuje równie literÚ formatujÈcÈ i (skrót od instruction), co po-
woduje wy wietlenie pamiÚci jako dezasemblowanych instrukcji jÚzyka asembler.

reader@hacking:~/booksrc $ gdb -q ./a.out
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) break main
Breakpoint 1 at 0x8048384: file firstprog.c, line 6.
(gdb) run
Starting program: /home/reader/booksrc/a.out

Breakpoint 1, main () at firstprog.c:6
6         for(i=0; i < 10; i++)
(gdb) i r $eip
eip            0x8048384      0x8048384 <main+16>
(gdb) x/i $eip
0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0
(gdb) x/3i $eip
0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0
0x804838b <main+23>: cmp DWORD PTR [ebp-4],0x9
0x804838f <main+27>: jle 0x8048393 <main+31>
(gdb) x/7xb $eip
0x8048384 <main+16>: 0xc7 0x45 0xfc 0x00 0x00        0x00   0x00
(gdb) x/i $eip
0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0
(gdb)




                                                                   Programowanie   45
W powy szym przykïadzie program a.out zostaï uruchomiony w GDB z punktem
             wstrzymania ustawionym w main(). Poniewa rejestr EIP wskazuje na pamiÚÊ, która
             faktycznie zawiera instrukcje w jÚzyku maszynowym, ïadnie poddajÈ siÚ one proce-
             sowi dezasemblacji.
                 Wcze niejsza dezasemblacja za pomocÈ objectdump potwierdza, e siedem bajtów,
             które wskazuje EIP, to faktycznie jÚzyk maszynowy dla odpowiedniej instrukcji
             asemblera.

             8048384:   c7 45 fc 00 00 00 00    mov    DWORD PTR [ebp-4],0x0


                 Ta instrukcja asemblera przenosi warto Ê 0 do pamiÚci znajdujÈcej siÚ pod ad-
             resem przechowywanym w rejestrze EBP minus 4. To wïa nie w tym miejscu pa-
             miÚci przechowywana jest zmienna i z jÚzyka C. Zmienna ta zostaïa zadeklarowana
             jako liczba caïkowita (int), wykorzystujÈca 4 bajty pamiÚci w przypadku procesora
             x86. To polecenie po prostu zeruje zmiennÈ i dla pÚtli for. Gdyby my teraz zbadali
             tÚ pamiÚÊ, zawieraïaby ona tylko przypadkowe mieci. PamiÚÊ w tej lokacji mo na
             zbadaÊ na ró ne sposoby:

             (gdb) i r ebp
             ebp            0xbffff808       0xbffff808
             (gdb) x/4xb $ebp - 4
             0xbffff804:     0xc0     0x83   0x04     0x08
             (gdb) x/4xb 0xbffff804
             0xbffff804:     0xc0     0x83   0x04     0x08
             (gdb) print $ebp - 4
             $1 = (void *) 0xbffff804
             (gdb) x/4xb $1
             0xbffff804:     0xc0     0x83   0x04     0x08
             (gdb) x/xw $1
             0xbffff804:     0x080483c0
             (gdb)


                  Rejestr EBP zawiera adres 0xbffff808, a instrukcja asemblera bÚdzie zapisywaïa
             do adresu o tej warto ci pomniejszonej o 4 — 0xbfffff804. Polecenie examine mo e
             zbadaÊ bezpo rednio ten adres pamiÚci lub wykonaÊ odpowiednie obliczenia w locie.
             Za pomocÈ polecenia print równie mo na wykonaÊ proste dziaïania arytmetyczne,
             a wynik zostanie zapisany w tymczasowej zmiennej w debugerze. Zmienna ta nosi
             nazwÚ $1 i mo e pó niej zostaÊ u yta do szybkiego uzyskania dostÚpu do okre lonego
             miejsca w pamiÚci. Ka da z przedstawionych wy ej metod pozwala uzyskaÊ ten
             sam rezultat: wy wietlenie znalezionych w pamiÚci 4 bajtów mieci, które zostanÈ
             wyzerowane po wykonaniu bie Ècej instrukcji.
                  Uruchommy bie ÈcÈ instrukcjÚ, korzystajÈc z polecenia nexti, bÚdÈcego skrótem
             dla next instruction (nastÚpna instrukcja). Procesor odczyta instrukcjÚ z EIP, wykona
             jÈ i przestawi EIP na kolejnÈ instrukcjÚ.




46   0x200
Hacking. Sztuka penetracji. Wydanie II
Hacking. Sztuka penetracji. Wydanie II
Hacking. Sztuka penetracji. Wydanie II
Hacking. Sztuka penetracji. Wydanie II
Hacking. Sztuka penetracji. Wydanie II
Hacking. Sztuka penetracji. Wydanie II

Weitere ähnliche Inhalte

Andere mochten auch

CSS. Witryny internetowe szyte na miarę. Autorytety informatyki. Wydanie II
CSS. Witryny internetowe szyte na miarę. Autorytety informatyki. Wydanie IICSS. Witryny internetowe szyte na miarę. Autorytety informatyki. Wydanie II
CSS. Witryny internetowe szyte na miarę. Autorytety informatyki. Wydanie IIWydawnictwo Helion
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychWydawnictwo Helion
 
FreeBSD 7. Instalacja i konfiguracja
FreeBSD 7. Instalacja i konfiguracjaFreeBSD 7. Instalacja i konfiguracja
FreeBSD 7. Instalacja i konfiguracjaWydawnictwo Helion
 
Kompresja dźwięku i obrazu wideo Real World
Kompresja dźwięku i obrazu wideo Real WorldKompresja dźwięku i obrazu wideo Real World
Kompresja dźwięku i obrazu wideo Real WorldWydawnictwo Helion
 
CSS i Ajax. Strony WWW zgodne ze standardami sieciowymi W3C
CSS i Ajax. Strony WWW zgodne ze standardami sieciowymi W3CCSS i Ajax. Strony WWW zgodne ze standardami sieciowymi W3C
CSS i Ajax. Strony WWW zgodne ze standardami sieciowymi W3CWydawnictwo Helion
 
USB. Praktyczne programowanie z Windows API w C++
USB. Praktyczne programowanie z Windows API w C++USB. Praktyczne programowanie z Windows API w C++
USB. Praktyczne programowanie z Windows API w C++Wydawnictwo Helion
 
Photoshop CS3/CS3 PL. Kanały i maski. Biblia
Photoshop CS3/CS3 PL. Kanały i maski. BibliaPhotoshop CS3/CS3 PL. Kanały i maski. Biblia
Photoshop CS3/CS3 PL. Kanały i maski. BibliaWydawnictwo Helion
 
ASP.NET 3.5 dla programistów PHP
ASP.NET 3.5 dla programistów PHPASP.NET 3.5 dla programistów PHP
ASP.NET 3.5 dla programistów PHPWydawnictwo Helion
 
FreeBSD. Podstawy administracji systemem. Wydanie II
FreeBSD. Podstawy administracji systemem. Wydanie IIFreeBSD. Podstawy administracji systemem. Wydanie II
FreeBSD. Podstawy administracji systemem. Wydanie IIWydawnictwo Helion
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaWydawnictwo Helion
 
Witryny nie do ukrycia. Jak zbudować stronę, którą znajdzie każda wyszukiwarka
Witryny nie do ukrycia. Jak zbudować stronę, którą znajdzie każda wyszukiwarkaWitryny nie do ukrycia. Jak zbudować stronę, którą znajdzie każda wyszukiwarka
Witryny nie do ukrycia. Jak zbudować stronę, którą znajdzie każda wyszukiwarkaWydawnictwo Helion
 
Informatyka Europejczyka. Podręcznik dla szkoły podstawowej, kl. IV - VI. Edy...
Informatyka Europejczyka. Podręcznik dla szkoły podstawowej, kl. IV - VI. Edy...Informatyka Europejczyka. Podręcznik dla szkoły podstawowej, kl. IV - VI. Edy...
Informatyka Europejczyka. Podręcznik dla szkoły podstawowej, kl. IV - VI. Edy...Wydawnictwo Helion
 
Oracle Database 11g. Programowanie w języku PL/SQL
Oracle Database 11g. Programowanie w języku PL/SQLOracle Database 11g. Programowanie w języku PL/SQL
Oracle Database 11g. Programowanie w języku PL/SQLWydawnictwo Helion
 

Andere mochten auch (15)

CSS. Witryny internetowe szyte na miarę. Autorytety informatyki. Wydanie II
CSS. Witryny internetowe szyte na miarę. Autorytety informatyki. Wydanie IICSS. Witryny internetowe szyte na miarę. Autorytety informatyki. Wydanie II
CSS. Witryny internetowe szyte na miarę. Autorytety informatyki. Wydanie II
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
 
FreeBSD 7. Instalacja i konfiguracja
FreeBSD 7. Instalacja i konfiguracjaFreeBSD 7. Instalacja i konfiguracja
FreeBSD 7. Instalacja i konfiguracja
 
Kompresja dźwięku i obrazu wideo Real World
Kompresja dźwięku i obrazu wideo Real WorldKompresja dźwięku i obrazu wideo Real World
Kompresja dźwięku i obrazu wideo Real World
 
CSS i Ajax. Strony WWW zgodne ze standardami sieciowymi W3C
CSS i Ajax. Strony WWW zgodne ze standardami sieciowymi W3CCSS i Ajax. Strony WWW zgodne ze standardami sieciowymi W3C
CSS i Ajax. Strony WWW zgodne ze standardami sieciowymi W3C
 
USB. Praktyczne programowanie z Windows API w C++
USB. Praktyczne programowanie z Windows API w C++USB. Praktyczne programowanie z Windows API w C++
USB. Praktyczne programowanie z Windows API w C++
 
Photoshop CS3/CS3 PL. Kanały i maski. Biblia
Photoshop CS3/CS3 PL. Kanały i maski. BibliaPhotoshop CS3/CS3 PL. Kanały i maski. Biblia
Photoshop CS3/CS3 PL. Kanały i maski. Biblia
 
ASP.NET 3.5 dla programistów PHP
ASP.NET 3.5 dla programistów PHPASP.NET 3.5 dla programistów PHP
ASP.NET 3.5 dla programistów PHP
 
FreeBSD. Podstawy administracji systemem. Wydanie II
FreeBSD. Podstawy administracji systemem. Wydanie IIFreeBSD. Podstawy administracji systemem. Wydanie II
FreeBSD. Podstawy administracji systemem. Wydanie II
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacja
 
Witryny nie do ukrycia. Jak zbudować stronę, którą znajdzie każda wyszukiwarka
Witryny nie do ukrycia. Jak zbudować stronę, którą znajdzie każda wyszukiwarkaWitryny nie do ukrycia. Jak zbudować stronę, którą znajdzie każda wyszukiwarka
Witryny nie do ukrycia. Jak zbudować stronę, którą znajdzie każda wyszukiwarka
 
Informatyka Europejczyka. Podręcznik dla szkoły podstawowej, kl. IV - VI. Edy...
Informatyka Europejczyka. Podręcznik dla szkoły podstawowej, kl. IV - VI. Edy...Informatyka Europejczyka. Podręcznik dla szkoły podstawowej, kl. IV - VI. Edy...
Informatyka Europejczyka. Podręcznik dla szkoły podstawowej, kl. IV - VI. Edy...
 
Bazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcieBazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcie
 
Oracle Database 11g. Programowanie w języku PL/SQL
Oracle Database 11g. Programowanie w języku PL/SQLOracle Database 11g. Programowanie w języku PL/SQL
Oracle Database 11g. Programowanie w języku PL/SQL
 
JavaScript. Pierwsze starcie
JavaScript. Pierwsze starcieJavaScript. Pierwsze starcie
JavaScript. Pierwsze starcie
 

Ähnlich wie Hacking. Sztuka penetracji. Wydanie II

.Net. Najpilniej strzeżone tajemnice
.Net. Najpilniej strzeżone tajemnice.Net. Najpilniej strzeżone tajemnice
.Net. Najpilniej strzeżone tajemniceWydawnictwo Helion
 
Anti-Hacker Tool Kit. Edycja polska
Anti-Hacker Tool Kit. Edycja polskaAnti-Hacker Tool Kit. Edycja polska
Anti-Hacker Tool Kit. Edycja polskaWydawnictwo Helion
 
The Shellcoders Handbook. Edycja polska
The Shellcoders Handbook. Edycja polskaThe Shellcoders Handbook. Edycja polska
The Shellcoders Handbook. Edycja polskaWydawnictwo Helion
 
Windows XP PL. Ilustrowany przewodnik
Windows XP PL. Ilustrowany przewodnikWindows XP PL. Ilustrowany przewodnik
Windows XP PL. Ilustrowany przewodnikWydawnictwo Helion
 
Wi-Foo. Sekrety bezprzewodowych sieci komputerowych
Wi-Foo. Sekrety bezprzewodowych sieci komputerowychWi-Foo. Sekrety bezprzewodowych sieci komputerowych
Wi-Foo. Sekrety bezprzewodowych sieci komputerowychWydawnictwo Helion
 
Vademecum hakera. Zabezpieczenia w Windows
Vademecum hakera. Zabezpieczenia w WindowsVademecum hakera. Zabezpieczenia w Windows
Vademecum hakera. Zabezpieczenia w WindowsWydawnictwo Helion
 
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatceFlash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatceWydawnictwo Helion
 
Hack Proofing Your Web Applications. Edycja polska
Hack Proofing Your Web Applications. Edycja polskaHack Proofing Your Web Applications. Edycja polska
Hack Proofing Your Web Applications. Edycja polskaWydawnictwo Helion
 
PHP. Praktyczne skrypty, które oszczędzą Twój czas
PHP. Praktyczne skrypty, które oszczędzą Twój czasPHP. Praktyczne skrypty, które oszczędzą Twój czas
PHP. Praktyczne skrypty, które oszczędzą Twój czasWydawnictwo Helion
 
101 zabezpieczeń przed atakami w sieci komputerowej
101 zabezpieczeń przed atakami w sieci komputerowej101 zabezpieczeń przed atakami w sieci komputerowej
101 zabezpieczeń przed atakami w sieci komputerowejWydawnictwo Helion
 
To tylko awaria, czyli katastrofy i wpadki z pecetem
To tylko awaria, czyli katastrofy i wpadki z pecetemTo tylko awaria, czyli katastrofy i wpadki z pecetem
To tylko awaria, czyli katastrofy i wpadki z pecetemWydawnictwo Helion
 
Sieci komputerowe. Budowa i działanie
Sieci komputerowe. Budowa i działanieSieci komputerowe. Budowa i działanie
Sieci komputerowe. Budowa i działanieWydawnictwo Helion
 
Bezpieczeństwo aplikacji tworzonych w technologii Ajax
Bezpieczeństwo aplikacji tworzonych w technologii AjaxBezpieczeństwo aplikacji tworzonych w technologii Ajax
Bezpieczeństwo aplikacji tworzonych w technologii AjaxWydawnictwo Helion
 
Wykrywanie włamań i aktywna ochrona danych
Wykrywanie włamań i aktywna ochrona danychWykrywanie włamań i aktywna ochrona danych
Wykrywanie włamań i aktywna ochrona danychWydawnictwo Helion
 
Profesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputerProfesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputerWydawnictwo Helion
 

Ähnlich wie Hacking. Sztuka penetracji. Wydanie II (20)

.Net. Najpilniej strzeżone tajemnice
.Net. Najpilniej strzeżone tajemnice.Net. Najpilniej strzeżone tajemnice
.Net. Najpilniej strzeżone tajemnice
 
Anti-Hacker Tool Kit. Edycja polska
Anti-Hacker Tool Kit. Edycja polskaAnti-Hacker Tool Kit. Edycja polska
Anti-Hacker Tool Kit. Edycja polska
 
The Shellcoders Handbook. Edycja polska
The Shellcoders Handbook. Edycja polskaThe Shellcoders Handbook. Edycja polska
The Shellcoders Handbook. Edycja polska
 
Windows XP PL. Ilustrowany przewodnik
Windows XP PL. Ilustrowany przewodnikWindows XP PL. Ilustrowany przewodnik
Windows XP PL. Ilustrowany przewodnik
 
Bezpieczny komputer w domu
Bezpieczny komputer w domuBezpieczny komputer w domu
Bezpieczny komputer w domu
 
Wi-Foo. Sekrety bezprzewodowych sieci komputerowych
Wi-Foo. Sekrety bezprzewodowych sieci komputerowychWi-Foo. Sekrety bezprzewodowych sieci komputerowych
Wi-Foo. Sekrety bezprzewodowych sieci komputerowych
 
Vademecum hakera. Zabezpieczenia w Windows
Vademecum hakera. Zabezpieczenia w WindowsVademecum hakera. Zabezpieczenia w Windows
Vademecum hakera. Zabezpieczenia w Windows
 
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatceFlash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
 
Hack Proofing Your Web Applications. Edycja polska
Hack Proofing Your Web Applications. Edycja polskaHack Proofing Your Web Applications. Edycja polska
Hack Proofing Your Web Applications. Edycja polska
 
Cracking bez tajemnic
Cracking bez tajemnicCracking bez tajemnic
Cracking bez tajemnic
 
PHP. Praktyczne skrypty, które oszczędzą Twój czas
PHP. Praktyczne skrypty, które oszczędzą Twój czasPHP. Praktyczne skrypty, które oszczędzą Twój czas
PHP. Praktyczne skrypty, które oszczędzą Twój czas
 
101 zabezpieczeń przed atakami w sieci komputerowej
101 zabezpieczeń przed atakami w sieci komputerowej101 zabezpieczeń przed atakami w sieci komputerowej
101 zabezpieczeń przed atakami w sieci komputerowej
 
To tylko awaria, czyli katastrofy i wpadki z pecetem
To tylko awaria, czyli katastrofy i wpadki z pecetemTo tylko awaria, czyli katastrofy i wpadki z pecetem
To tylko awaria, czyli katastrofy i wpadki z pecetem
 
Sieci komputerowe. Budowa i działanie
Sieci komputerowe. Budowa i działanieSieci komputerowe. Budowa i działanie
Sieci komputerowe. Budowa i działanie
 
Mandrake Linux
Mandrake LinuxMandrake Linux
Mandrake Linux
 
Bezpieczeństwo aplikacji tworzonych w technologii Ajax
Bezpieczeństwo aplikacji tworzonych w technologii AjaxBezpieczeństwo aplikacji tworzonych w technologii Ajax
Bezpieczeństwo aplikacji tworzonych w technologii Ajax
 
Wykrywanie włamań i aktywna ochrona danych
Wykrywanie włamań i aktywna ochrona danychWykrywanie włamań i aktywna ochrona danych
Wykrywanie włamań i aktywna ochrona danych
 
Profesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputerProfesjonalne programowanie. Część 1. Zrozumieć komputer
Profesjonalne programowanie. Część 1. Zrozumieć komputer
 
ABC sieci komputerowych
ABC sieci komputerowychABC sieci komputerowych
ABC sieci komputerowych
 
ABC Neostrada
ABC NeostradaABC Neostrada
ABC Neostrada
 

Mehr von Wydawnictwo Helion

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyWydawnictwo Helion
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikWydawnictwo Helion
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczneWydawnictwo Helion
 
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieE-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieWydawnictwo Helion
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsWydawnictwo Helion
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IIWydawnictwo Helion
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuWydawnictwo Helion
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIWydawnictwo Helion
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningWydawnictwo Helion
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykWydawnictwo Helion
 
Serwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanieSerwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanieWydawnictwo Helion
 
Microsoft Visual Studio 2008. Księga eksperta
Microsoft Visual Studio 2008. Księga ekspertaMicrosoft Visual Studio 2008. Księga eksperta
Microsoft Visual Studio 2008. Księga ekspertaWydawnictwo Helion
 
Rewizor GT. Prowadzenie ewidencji księgowej
Rewizor GT. Prowadzenie ewidencji księgowejRewizor GT. Prowadzenie ewidencji księgowej
Rewizor GT. Prowadzenie ewidencji księgowejWydawnictwo Helion
 

Mehr von Wydawnictwo Helion (20)

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. Projekty
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnik
 
Access w biurze i nie tylko
Access w biurze i nie tylkoAccess w biurze i nie tylko
Access w biurze i nie tylko
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
 
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesieE-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image&#39;u w biznesie
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółu
 
Windows PowerShell. Podstawy
Windows PowerShell. PodstawyWindows PowerShell. Podstawy
Windows PowerShell. Podstawy
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie II
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny trening
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktyk
 
Excel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktykExcel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
 
Access 2007 PL. Seria praktyk
Access 2007 PL. Seria praktykAccess 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
 
Word 2007 PL. Seria praktyk
Word 2007 PL. Seria praktykWord 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
 
AutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PLAutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PL
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
 
Serwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanieSerwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanie
 
Microsoft Visual Studio 2008. Księga eksperta
Microsoft Visual Studio 2008. Księga ekspertaMicrosoft Visual Studio 2008. Księga eksperta
Microsoft Visual Studio 2008. Księga eksperta
 
Rewizor GT. Prowadzenie ewidencji księgowej
Rewizor GT. Prowadzenie ewidencji księgowejRewizor GT. Prowadzenie ewidencji księgowej
Rewizor GT. Prowadzenie ewidencji księgowej
 

Hacking. Sztuka penetracji. Wydanie II

  • 1. Hacking. Sztuka penetracji. Wydanie II Autor: Jon Erickson T³umaczenie: Marcin Rogó¿ ISBN: 978-83-246-1802-6 Tytu³ orygina³u: Hacking: The Art of Exploitation, 2nd Edition Format: 170x230, stron: 520 Zdob¹dŸ wiedzê godn¹ hakera! • Co trzeba wiedzieæ, aby byæ hakerem? • Jak ³amaæ has³a? • Jak uzyskaæ dostêp do zabezpieczonej sieci bezprzewodowej? S³owo haker kojarzy nam siê z komputerowym mistrzem manipulacji Kevinem Mitnickiem. Pojêcie to jednak ewoluowa³o od czasu jego spektakularnych akcji. Zatem kim jest dziœ haker? Wbrew obiegowej opinii, wiêkszoœæ hakerów nie wykorzystuje swej wiedzy do niecnych celów. Dziêki swej wiedzy i dociekliwoœci przyczyniaj¹ siê do rozwoju bezpieczeñstwa sieci i programów. Nikt bowiem nie potrafi tak jak oni zg³êbiaæ sposoby dzia³ania zaawansowanego oprogramowania i sprzêtu i tropiæ luki pozwalaj¹ce na atak lub wyciek danych oraz przewidywaæ mo¿liwe problemy w ich dzia³aniu. Jon Erickson w ksi¹¿ce Hacking. Sztuka penetracji. Wydanie II omawia te zagadnienia ze œwiata informatyki, które nie mog¹ byæ obce hakerowi. Dziêki tej ksi¹¿ce poznasz m.in. podstawy jêzyka C oraz dowiesz siê, jak wykorzystaæ jego s³aboœci oraz potkniêcia programistów pisz¹cych w tym jêzyku. Zapoznasz siê z podstawami funkcjonowania sieci i zdobêdziesz wiedzê o modelu OSI, a tak¿e nauczysz siê pods³uchiwaæ transmitowane w sieci dane, skanowaæ porty i ³amaæ has³a. • Programowanie w jêzyku C • Model OSI • Pods³uchiwanie sieci • Skanowanie portów • Sposoby ³amania hase³ • Szyfrowanie danych i po³¹czeñ • Sposoby atakowania sieci bezprzewodowych Wydawnictwo Helion Oto elementarz prawdziwego hakera! ul. Koœciuszki 1c 44-100 Gliwice tel. 032 230 98 63 e-mail: helion@helion.pl
  • 2. SPIS TRE¥CI PRZE DMOWA 11 P ODZI} KO W ANI A 12 0X100 WPROWAD ZENIE 13 0X200 PR OGR AMOWANIE 19 0x210 Istota programowania .....................................................................................20 0x220 Pseudokod ......................................................................................................22 0x230 Struktury sterujÈce ...........................................................................................22 0x231 If-Then-Else ........................................................................................22 0x232 PÚtle While/Until ................................................................................24 0x233 PÚtle for .............................................................................................25 0x240 Podstawowe pojÚcia programistyczne .............................................................26 0x241 Zmienne .............................................................................................26 0x242 Operatory arytmetyczne .....................................................................27 0x243 Operatory porównania .......................................................................28 0x244 Funkcje ...............................................................................................30 0x250 Zaczynamy brudziÊ sobie rÚce ..........................................................................34 0x251 WiÚkszy obraz ....................................................................................35 0x252 Procesor x86 ......................................................................................38 0x253 JÚzyk asembler ...................................................................................40 0x260 Wracamy do podstaw .....................................................................................53 0x261 ’añcuchy ............................................................................................53 0x262 Ze znakiem, bez znaku, dïuga i krótka ................................................57 0x263 Wska niki ...........................................................................................59 0x264 ’añcuchy formatujÈce .........................................................................63
  • 3. 0x265 Rzutowanie typów .............................................................................67 0x266 Argumenty wiersza poleceñ ...............................................................74 0x267 ZasiÚg zmiennych ...............................................................................78 0x270 Segmentacja pamiÚci .......................................................................................85 0x271 Segmenty pamiÚci w jÚzyku C ............................................................92 0x272 Korzystanie ze sterty ...........................................................................94 0x273 Funkcja malloc() ze sprawdzaniem bïÚdów .........................................96 0x280 Budujemy na podstawach ...............................................................................98 0x281 DostÚp do plików ...............................................................................98 0x282 Prawa dostÚpu do plików .................................................................104 0x283 Identyfikatory u ytkowników ............................................................105 0x284 Struktury ..........................................................................................114 0x285 Wska niki do funkcji .........................................................................117 0x286 Liczby pseudolosowe ........................................................................118 0x287 Gry hazardowe .................................................................................120 0X300 NADU¿YCI A 133 0x310 Uogólnione techniki nadu yÊ .........................................................................136 0x320 Przepeïnienia bufora ......................................................................................137 0x321 Luki zwiÈzane z przepeïnieniem stosowym .......................................140 0x330 Eksperymenty z BASH ....................................................................................152 0x331 Wykorzystanie rodowiska ...............................................................161 0x340 Przepeïnienia w innych segmentach ..............................................................170 0x341 Podstawowe przepeïnienie na stercie ...............................................170 0x342 Przepeïnienia wska ników funkcyjnych .............................................176 0x350 ’añcuchy formatujÈce ....................................................................................187 0x351 Parametry formatujÈce .....................................................................188 0x352 Podatno Ê ciÈgów formatujÈcych na ataki ........................................190 0x353 Odczyt spod dowolnych adresów pamiÚci ........................................192 0x354 Zapis pod dowolnymi adresami pamiÚci ...........................................193 0x355 Bezpo redni dostÚp do parametrów .................................................201 0x356 U ycie zapisu krótkich liczb caïkowitych ...........................................203 0x357 Obej cia z u yciem sekcji dtors .........................................................205 0x358 Kolejny sïaby punkt programu notesearch ........................................210 0x359 Nadpisywanie globalnej tabeli przesuniÚÊ ........................................212 0X400 SIEC I 217 0x410 Model OSI .....................................................................................................217 0x420 Gniazda .........................................................................................................220 0x421 Funkcje obsïugujÈce gniazda ............................................................221 0x422 Adresy gniazd ..................................................................................223 0x423 Sieciowa kolejno Ê bajtów ................................................................224 0x424 Konwersja adresu internetowego .....................................................225 6 Hacking. Sztuka penetracji
  • 4. 0x425 Prosty przykïad serwera ....................................................................226 0x426 Przykïad klienta WWW .....................................................................230 0x427 Maleñki serwer WWW ......................................................................235 0x430 ZaglÈdamy do ni szych warstw .....................................................................240 0x431 Warstwa ïÈcza danych ......................................................................240 0x432 Warstwa sieci ...................................................................................242 0x433 Warstwa transportowa .....................................................................244 0x440 Podsïuchiwanie w sieci ..................................................................................247 0X441 Sniffer surowych pakietów ...............................................................249 0x442 Sniffer libpcap ..................................................................................251 0x443 Dekodowanie warstw ......................................................................253 0x444 Aktywne podsïuchiwanie .................................................................263 0x450 Odmowa usïugi .............................................................................................276 0x451 Zalew pakietów SYN (SYN Flooding) .................................................276 0x452 Atak Ping of Death ...........................................................................281 0x453 Atak Teardrop ..................................................................................281 0x454 Zalew pakietów ping (Ping Flooding) ................................................281 0x455 Atak ze wzmocnieniem (Amplification) .............................................282 0x456 Rozproszony atak DoS ......................................................................283 0x460 PrzejÚcie TCP/IP .............................................................................................283 0x461 RozïÈczanie za pomocÈ RST ..............................................................283 0x462 PrzejÚcie z kontynuacjÈ .....................................................................289 0x470 Skanowanie portów ......................................................................................289 0x471 Ukryte skanowanie SYN ....................................................................289 0x472 Skanowanie FIN, X-mas i Null ...........................................................290 0x473 Skanowanie z ukrycia .......................................................................290 0x474 Skanowanie z u yciem bezczynnego komputera ...............................291 0x475 Zabezpieczenie wyprzedzajÈce (Shroud) ...........................................293 0x480 Id i wïam siÚ gdzie .....................................................................................298 0x481 Analiza z u yciem GDB .....................................................................299 0x482 Prawie ma znaczenie ........................................................................301 0x483 Shellcode wiÈ Ècy port .....................................................................304 0X500 SHE LLCODE 309 0x510 Asembler a C .................................................................................................309 0x511 Linuksowe wywoïania systemowe w asemblerze .............................312 0x520 ¥cie ka do shellcode ......................................................................................315 0x521 Instrukcje asemblera wykorzystujÈce stos .........................................315 0x522 Badanie za pomocÈ GDB ..................................................................317 0x523 Usuwanie bajtów zerowych ..............................................................319 0x530 Kod wywoïujÈcy powïokÚ ..............................................................................324 0x531 Kwestia uprawnieñ ...........................................................................328 0x532 Skracamy jeszcze bardziej .................................................................331 Spis tre ci 7
  • 5. 0x540 Kod powïoki wiÈ Ècy port .............................................................................332 0x541 Duplikowanie standardowych deskryptorów plików .........................336 0x542 RozgaïÚziajÈce struktury sterujÈce ....................................................338 0x550 Shellcode nawiÈzujÈcy poïÈczenie powrotne .................................................343 0X600 ¥R OD KI ZAPOBI EGAWC ZE 349 0x610 ¥rodki zapobiegawcze, które wykrywajÈ .......................................................350 0x620 Demony systemowe ......................................................................................351 0x621 Bïyskawiczne wprowadzenie do sygnaïów .......................................352 0x622 Demon tinyweb ................................................................................354 0x630 NarzÚdzia pracy .............................................................................................358 0x631 NarzÚdzie nadu ywajÈce tinywebd ...................................................359 0x640 Pliki dziennika ...............................................................................................364 0x641 Wmieszaj siÚ w tïum ........................................................................365 0x650 Przeoczywszy oczywiste ................................................................................366 0x651 Krok po kroku ...................................................................................367 0x652 Ponowne skïadanie wszystkiego ......................................................371 0x653 Robocze procesy potomne ................................................................377 0x660 Zaawansowana sztuka kamufla u .................................................................378 0x661 Faïszowanie rejestrowanego adresu IP .............................................379 0x662 Nierejestrowane nadu ycie ...............................................................383 0x670 Caïa infrastruktura .........................................................................................386 0x671 Ponowne wykorzystanie gniazda ......................................................386 0x680 Przemyt ïadunku ............................................................................................390 0x681 Kodowanie ïañcuchów .....................................................................391 0x682 Jak ukryÊ puïapkÚ? ...........................................................................394 0x690 Ograniczenia bufora ......................................................................................395 0x691 Polimorficzny kod powïoki z drukowalnymi znakami ASCII ...............397 0x6a0 Zabezpieczenia wzmacniajÈce .......................................................................408 0x6b0 Niewykonywalny stos ....................................................................................408 0x6b1 Powracanie do funkcji biblioteki libc .................................................409 0x6b2 Powrót do funkcji system() ...............................................................409 0x6c0 Randomizacja przestrzeni stosu .....................................................................411 0x6c1 Badanie za pomocÈ BASH i GDB .......................................................413 0x6c2 Odbijanie od linux-gate ....................................................................417 0x6c3 Wiedza stosowana ...........................................................................420 0x6c4 Pierwsza próba .................................................................................421 0x6c5 Gramy w ko ci ..................................................................................422 0X700 KRYP TOLOGIA 425 0x710 Teoria informacji ............................................................................................426 0x711 Bezwarunkowe bezpieczeñstwo .......................................................426 0x712 Szyfr z kluczem jednorazowym .........................................................426 8 Hacking. Sztuka penetracji
  • 6. 0x713 Kwantowa dystrybucja kluczy ...........................................................427 0x714 Bezpieczeñstwo obliczeniowe ...........................................................428 0x720 Rozlegïo Ê algorytmów .................................................................................429 0x721 Notacja asymptotyczna .....................................................................430 0x730 Szyfrowanie symetryczne ...............................................................................430 0x731 Kwantowy algorytm przeszukiwania autorstwa Lova Grovera ...........432 0x740 Szyfrowanie asymetryczne .............................................................................432 0x741 RSA ..................................................................................................433 0x742 Kwantowy algorytm rozkïadu na czynniki autorstwa Petera Shora ....437 0x750 Szyfry hybrydowe ..........................................................................................438 0x751 Ataki z ukrytym po rednikiem ...........................................................439 0x752 „Odciski palców” komputerów w protokole SSH ...............................443 0x753 Rozmyte „odciski palców” ................................................................447 0x760 ’amanie haseï ...............................................................................................451 0x761 Ataki sïownikowe .............................................................................453 0x762 Ataki na zasadzie peïnego przeglÈdu ................................................455 0x763 Tablica wyszukiwania skrótów .........................................................457 0x764 Macierz prawdopodobieñstwa haseï ................................................457 0x770 Szyfrowanie w sieci bezprzewodowej 802.11b ..............................................467 0x771 Protokóï Wired Equivalent Privacy (WEP) ..........................................468 0x772 Szyfr strumieniowy RC4 ....................................................................469 0x780 Ataki na WEP ................................................................................................470 0x781 Ataki na zasadzie peïnego przeglÈdu w trybie offline .......................470 0x782 Ponowne u ycie strumienia klucza ....................................................471 0x783 Tablice sïownikowe z wektorami IV ..................................................472 0x784 Przekierowanie IP .............................................................................473 0x785 Atak Fluhrera, Mantina i Shamira (FMS) ............................................474 0X800 P ODSUMOWANIE 485 0x810 Bibliografia i dodatkowe informacje ..............................................................486 0x820 Kody ródïowe ..............................................................................................487 O P ’YC IE C D 489 SKOR OWID Z 491 Spis tre ci 9
  • 7. 0x200 PROGRAMOWANIE Haker to termin u ywany do okre lenia zarówno piszÈcych kod, jak i tych, którzy wykorzystujÈ znajdujÈce siÚ w nim bïÚdy. ChoÊ obie grupy hakerów majÈ ró ne cele, to i jedni, i drudzy stosujÈ podobne techniki rozwiÈzywania problemów. A ze wzglÚdu na fakt, e umiejÚt- no Ê programowania pomaga tym, którzy wykorzystujÈ bïÚdy w kodzie, za zrozumienie metod zastosowania pomaga tym, którzy programujÈ, wielu hakerów robi obie rzeczy jednocze nie. InteresujÈce rozwiÈzania istniejÈ i w zakresie technik pisania eleganckiego kodu, i technik sïu Ècych do wykorzysty- wania sïabo ci programów. Hakerstwo to w rzeczywisto ci akt znajdowania pomy- sïowych i nieintuicyjnych rozwiÈzañ problemów. Metody stosowane w narzÚdziach wykorzystujÈcych sïabo ci programów zwy- kle sÈ zwiÈzane z zastosowaniem reguï funkcjonowania komputera w sposób, któ- rego nigdy nie brano pod uwagÚ — pozornie magiczne rezultaty osiÈga siÚ zwykle po skupieniu siÚ na omijaniu zaimplementowanych zabezpieczeñ. Metody u ywa- ne podczas pisania programów sÈ podobne, bo równie wykorzystujÈ reguïy funk- cjonowania komputera w nowy i pomysïowy sposób, jednak w tym przypadku koñco- wym celem jest osiÈgniÚcie najbardziej wydajnego lub najkrótszego kodu ródïowego. Istnieje nieskoñczenie wiele programów, które mo na napisaÊ w celu wykonania do- wolnego zadania, jednak wiÚkszo Ê z istniejÈcych rozwiÈzañ jest niepotrzebnie obszerna, zïo ona i niedopracowana. Pozostaïa niewielka ich liczba to programy niedu e, wydajne i estetyczne. Ta wïa ciwo Ê programów nosi nazwÚ elegancji, za przemy lane i pomysïowe rozwiÈzania prowadzÈce do takiej wydajno ci nazywane sÈ sztuczkami (ang. hacks). Hakerzy stojÈcy po obu stronach metodyki programowania doceniajÈ zarówno piÚkno eleganckiego kodu, jak i geniusz pomysïowych sztuczek.
  • 8. W wiecie biznesu mniejszÈ wagÚ przykïada siÚ do przemy lanych metod pro- gramowania i eleganckiego kodu, a wiÚkszÈ do tworzenia funkcjonalnego kodu w jak najkrótszym czasie i jak najtaniej. Ze wzglÚdu na gwaïtowny wzrost mocy obli- czeniowej oraz dostÚpno ci pamiÚci po wiÚcenie dodatkowych piÚciu godzin na opracowanie nieco szybszego i mniej wymagajÈcego pod wzglÚdem pamiÚci frag- mentu kodu po prostu nie opïaca siÚ, gdy mamy do czynienia z nowoczesnymi kom- puterami dysponujÈcymi gigahercowymi cyklami procesora i gigabajtami pamiÚci. Podczas gdy optymalizacje czasu i wykorzystania pamiÚci pozostajÈ niezauwa one przez wiÚkszo Ê (z wyjÈtkiem wyrafinowanych) u ytkowników, nowa funkcjonal- no Ê ma potencjaï marketingowy. Kiedy najwa niejszym kryterium sÈ pieniÈdze, po wiÚcanie czasu na opracowywanie przemy lanych sztuczek optymalizacyjnych nie ma po prostu sensu. ElegancjÚ programowania pozostawiono hakerom, hobbistom komputerowym, których celem nie jest zarabianie, lecz wyci niÚcie wszystkiego, co siÚ da, z ich sta- rych maszyn Commodore 64, autorom programów wykorzystujÈcych bïÚdy, piszÈ- cym niewielkie i niesamowite fragmenty kodu, dziÚki którym potrafiÈ przedostawaÊ siÚ przez wÈskie szczeliny systemów zabezpieczeñ, oraz wszystkim innym doceniajÈ- cym warto Ê szukania i znajdowania najlepszych mo liwych rozwiÈzañ. SÈ to osoby zachwycajÈce siÚ mo liwo ciami oferowanymi przez programowanie i dostrzegajÈce piÚkno eleganckich fragmentów kodu oraz geniusz przemy lanych sztuczek. Poznanie istoty programowania jest niezbÚdne do zrozumienia, w jaki sposób mo na wykorzy- stywaÊ sïabo ci programów, dlatego te programowanie to naturalny punkt wyj cia dla naszych rozwa añ. 0x210 Istota programowania Programowanie to pojÚcie niezmiernie naturalne i intuicyjne. Program jest tylko seriÈ instrukcji zapisanych w okre lonym jÚzyku. Programy wystÚpujÈ wszÚdzie i nawet technofoby codziennie korzystajÈ z programów. Opisywanie drogi dojazdu w jakie miejsce, przepisy kulinarne, rozgrywki piïkarskie i spirale DNA to sÈ ró - nego typu programy. Typowy „program” opisu dojazdu samochodem w konkretne miejsce mo e wyglÈdaÊ tak: Najpierw zjed w dó Alejæ Ko ciuszki, prowadzæcæ na wschód. Jed niæ do momentu, kiedy zobaczysz po prawej stronie ko ció . Je eli ulica búdzie zablokowana ze wzglúdu na prowadzone roboty, skrúè w prawo w ul. Moniuszki, potem skrúè w lewo w ul. Prusa i w ko cu skrúè w prawo w ul. Orzeszkowej. W przeciwnym razie mo esz po prostu kontynuowaè jazdú Alejæ Ko ciuszki i skrúciè w ul. Orzeszkowej. Jed niæ i skrúè w ul. Docelowæ. Jed niæ jakie 8 kilometrów — nasz dom búdzie siú znajdowa po prawej stronie. Dok adny adres to ul. Docelowa 743. Ka dy, kto zna jÚzyk polski, pojmie podane instrukcje i bÚdzie mógï kierowaÊ siÚ nimi podczas jazdy. Bez wÈtpienia nie zapisano ich zbyt bïyskotliwie, ale sÈ jed- noznaczne i zrozumiaïe. 20 0x200
  • 9. Jednak komputer nie zna jÚzyka polskiego — rozumie jedynie jÚzyk maszynowy (ang. machine language). W celu poinstruowania go, aby wykonaï pewnÈ czynno Ê, instrukcjÚ tÚ nale y zapisaÊ w zrozumiaïym dla niego jÚzyku. Jednak e jÚzyk ma- szynowy jest bardzo ezoteryczny i trudny do opanowania. Skïada siÚ z serii bitów oraz bajtów i ró ni siÚ, w zale no ci od danej architektury komputerowej. Tak wiÚc w celu napisania programu w jÚzyku maszynowym dla procesora z rodziny Intel x86 nale y okre liÊ warto Ê zwiÈzanÈ z ka dÈ instrukcjÈ, sposób interakcji poszczególnych instrukcji oraz mnóstwo innych niskopoziomowych szczegóïów. Tego rodzaju pro- gramowanie jest bardzo niewdziÚcznym oraz kïopotliwym zadaniem i z pewno ciÈ nie jest intuicyjne. Do pokonania komplikacji zwiÈzanych z pisaniem programów w jÚzyku maszy- nowym potrzebny jest translator. JednÈ z form translatora jÚzyka maszynowego jest asembler. To program, który tïumaczy jÚzyk asemblera na kod zapisany w jÚzyku maszynowym. JÚzyk asemblera jest bardziej przystÚpny od kodu maszynowego, poniewa dla ró nych instrukcji i zmiennych wykorzystuje nazwy (mnemoniki), a nie same warto ci liczbowe. Jednak jÚzyk asemblera wciÈ jest daleki od intuicyjnego. Nazwy instrukcji sÈ ezoteryczne, a sam jÚzyk wciÈ jest zale ny od architektury. Oznacza to, e tak samo, jak jÚzyk maszynowy dla procesorów Intel x86 ró ni siÚ od jÚzyka maszynowego dla procesorów Sparc, jÚzyk asemblera x86 jest ró ny od jÚzyka asemblera Sparc. ¿aden program napisany przy u yciu jÚzyka asemblera dla architektury jednego procesora nie bÚdzie dziaïaï w architekturze innego procesora. Je eli program zostaï napisany w jÚzyku asemblera x86, musi zostaÊ przepisany, aby mo na byïo uruchomiÊ go w architekturze Sparc. Ponadto w celu napisania wydaj- nego programu w jÚzyku asemblera nale y znaÊ wiele niskopoziomowych szczegó- ïów, dotyczÈcych architektury danego procesora. Problemów tych mo na uniknÈÊ przy u yciu kolejnej formy translatora, noszÈ- cego nazwÚ kompilatora (ang. compiler). Kompilator konwertuje kod zapisany w jÚzy- ku wysokopoziomowym do postaci kodu maszynowego. JÚzyki wysokopoziomowe sÈ o wiele bardziej intuicyjne od jÚzyka asemblera i mogÈ byÊ konwertowane do wielu ró nych typów jÚzyka maszynowego dla odmiennych architektur procesorów. Ozna- cza to, e je li zapisze siÚ program w jÚzyku wysokiego poziomu, ten sam kod mo e zostaÊ skompilowany przez kompilator do postaci kodu maszynowego dla ró nych architektur. C, C++ lub FORTRAN to przykïady jÚzyków wysokopoziomowych. Program napisany w takim jÚzyku jest o wiele bardziej czytelny1 od jÚzyka asem- blera lub maszynowego, choÊ wciÈ musi byÊ zgodny z bardzo surowymi reguïami dotyczÈcymi sposobu wyra ania instrukcji, poniewa w przeciwnym razie kompila- tor nie bÚdzie w stanie ich zrozumieÊ. 1 Oczywi cie pod warunkiem, e przez czytelny rozumiemy taki, który przypomina jÚzyk angielski — przyp. tïum. Programowanie 21
  • 10. 0x220 Pseudokod Programi ci dysponujÈ jeszcze jednym rodzajem jÚzyka programowania, noszÈcym nazwÚ pseudokodu. Pseudokod (ang. pseudo-code) to po prostu wyra enia zapisane w jÚzyku naturalnym, ustawione w strukturÚ ogólnie przypominajÈcÈ jÚzyk wyso- kopoziomowy. Nie jest on rozumiany przez kompilatory, asemblery ani kompute- ry, ale stanowi przydatny sposób skïadania instrukcji. Pseudokod nie jest dobrze zdefiniowany. W rzeczywisto ci wiele osób zapisuje pseudokod odmiennie. Jest to rodzaj nieokre lonego, brakujÈcego ogniwa miÚdzy jÚzykami naturalnymi, takimi jak angielski lub polski, a wysokopoziomowymi jÚzykami programowania, takimi jak C lub Pascal. Pseudokod stanowi wietne wprowadzenie do uniwersalnych zaïo eñ programistycznych. 0x230 Struktury sterujÈce Bez struktur sterujÈcych program byïby jedynie seriÈ kolejno wykonywanych instruk- cji. Jest to wystarczajÈce w przypadku bardzo prostych programów, ale wiÚkszo Ê programów, takich jak np. opis dojazdu, taka nie jest. Prezentowany opis dojazdu zawieraï instrukcje: Jed niÈ do momentu, kiedy zobaczysz po prawej stronie ko cióï. Je eli ulica bÚdzie zablokowana ze wzglÚdu na prowadzone roboty… Instrukcje te nazywamy strukturami sterujÈcymi, poniewa zmieniajÈ przebieg wykonywania programu z prostego, sekwencyjnego, na bardziej zïo ony i u yteczny. 0x231 If-Then-Else W naszym opisie dojazdu Aleja Ko ciuszki mo e byÊ w remoncie. Do rozwiÈzania problemu wynikajÈcego z tej sytuacji potrzebujemy specjalnego zestawu instrukcji. Je eli zdefiniowane okoliczno ci nie wystÈpiÈ (remont), bÚdÈ wykonywane standardo- we instrukcje. Tego rodzaju specjalne przypadki mo na wziÈÊ pod uwagÚ w progra- mie, korzystajÈc z jednej z najbardziej naturalnych struktur sterujÈcych: if-then-else (je eli-wówczas-w przeciwnym przypadku). Ogólnie wyglÈda to mniej wiÚcej tak: If (warunek) then { Zestaw instrukcji do wykonania, gdy warunek jest spe niony; } Else { Zestaw instrukcji do wykonania, gdy warunek nie jest spe niony; } W tej ksiÈ ce bÚdziemy posïugiwali siÚ pseudokodem przypominajÈcym jÚzyk C, wiÚc ka da instrukcja bÚdzie zakoñczona rednikiem, a ich zbiory bÚdÈ grupowane za pomocÈ nawiasów klamrowych i wyró niane wciÚciem. Pseudokod struktury if-then-else dla wskazówek dojazdu mógïby przedstawiaÊ siÚ nastÚpujÈco: 22 0x200
  • 11. Jed w dó Alejæ Ko ciuszki; Je eli (ulica zablokowana) { Skrúè w prawo w ul. Moniuszki; Skrúè w lewo w ul. Prusa; Skrúè w prawo w ul. Orzeszkowej; } else { Skrúè w prawo w ul. Orzeszkowej; } Ka da instrukcja znajduje siÚ w osobnym wierszu, a ró ne zestawy instrukcji warunkowych sÈ zgrupowane wewnÈtrz nawiasów klamrowych i dla zwiÚkszenia czytelno ci zastosowano dla nich wciÚcie. W C i wielu innych jÚzykach programo- wania sïowo kluczowe then jest domniemane i tym samym pomijane, wiÚc pomi- nÚli my je równie w pseudokodzie. Oczywi cie, istniejÈ jÚzyki, których skïadnia wymaga zastosowania sïowa klu- czowego then — przykïadami mogÈ tu byÊ BASIC, Fortran, a nawet Pascal. Tego typu ró nice syntaktyczne miÚdzy jÚzykami programowania sÈ niemal nieistotne, jako e podstawowa struktura jest taka sama. Gdy programista zrozumie zaïo enia tych jÚzyków, nauczenie siÚ ró nych odmian syntaktycznych jest stosunkowo ïatwe. Poniewa w dalszych rozdziaïach bÚdziemy programowali w jÚzyku C, prezento- wany pseudokod bÚdzie przypominaï ten jÚzyk. Nale y jednak pamiÚtaÊ, e mo e on przyjmowaÊ ró ne postaci. InnÈ powszechnÈ reguïÈ skïadni podobnej do C jest sytuacja, w której zestaw instrukcji umieszczonych w nawiasach klamrowych zawiera tylko jednÈ instrukcjÚ. Dla zwiÚkszenia czytelno ci wciÈ warto dla takiej instrukcji zastosowaÊ wciÚcie, ale nie jest ono wymagane. Zgodnie z tÈ reguïÈ mo na wiÚc napisaÊ wcze niej przed- stawiony opis dojazdu tak, aby uzyskaÊ równowa ny fragment pseudokodu: Jed w dó Alejæ Ko ciuszki; Je eli (ulica zablokowana) { Skrúè w prawo w ul. Moniuszki; Skrúè w lewo w ul. Prusa; Skrúè w prawo w ul. Orzeszkowej; } else Skrúè w prawo w ul. Orzeszkowej; Reguïa mówiÈca o zestawach instrukcji dotyczy wszystkich struktur sterujÈcych opisywanych w niniejszej ksiÈ ce, a samÈ reguïÚ równie mo na zapisaÊ w pseu- dokodzie. Programowanie 23
  • 12. If (w zestawie instrukcji znajduje siú tylko jedna instrukcja) U ycie nawiasów klamrowych do zgrupowania instrukcji jest opcjonalne; Else { U ycie nawiasów klamrowych jest niezbúdne; Poniewa musi istnieè logiczny sposób zgrupowania tych instrukcji; } Nawet opis skïadni mo na potraktowaÊ jak program. Istnieje wiele odmian struk- tury if-then-else, np. instrukcje select i case, ale logika pozostaje taka sama: je eli stanie siÚ tak, zrób to i to, w przeciwnym przypadku wykonaj, co poni ej (a poni ej mogÈ siÚ znajdowaÊ kolejne instrukcje if-then). 0x232 PÚtle While/Until Innym podstawowym pojÚciem programistycznym jest struktura sterujÈca while, bÚdÈca rodzajem pÚtli. Programista czÚsto chce wykonaÊ zestaw instrukcji kilka razy. Program mo e wykonaÊ to zadanie, stosujÈc pÚtlÚ, ale wymaga to okre lenia warun- ków jej zakoñczenia, aby nie trwaïa w nieskoñczono Ê. PÚtla while wykonuje podany zestaw instrukcji, dopóki warunek jest prawdziwy. Prosty program dla gïodnej myszy mógïby wyglÈdaÊ nastÚpujÈco: While (jeste g odna) { Znajd jakie jedzenie; Zjedz jedzenie; } Te dwa zestawy instrukcji za instrukcjÈ while bÚdÈ powtarzane, dopóki mysz bÚdzie gïodna. Ilo Ê po ywienia odnalezionego przez mysz przy ka dej próbie mo e wahaÊ siÚ od maïego okruszka po caïy bochen chleba. Podobnie liczba wykonañ zestawu instrukcji w pÚtli while zale y od ilo ci po ywienia znalezionego przez mysz. OdmianÈ pÚtli while jest pÚtla until, wykorzystywana w Perlu (w C skïadnia ta nie jest u ywana). PÚtla until jest po prostu pÚtlÈ while z odwróconym warunkiem. Ten sam program dla myszy zapisany z u yciem pÚtli until wyglÈdaïby nastÚpujÈco: Until (nie jeste g odna) { Znajd jakie jedzenie; Zjedz jedzenie; } Logicznie ka da instrukcja podobna do until mo e byÊ przeksztaïcona w pÚtlÚ while. Opis dojazdu zawieraï zdanie: „Jed niÈ do momentu, kiedy zobaczysz po prawej stronie ko cióï”. Mo emy to w prosty sposób przeksztaïciÊ w standardowÈ pÚtlÚ while — wystarczy, e odwrócimy warunek: 24 0x200
  • 13. While (nie ma ko cio a po prawej stronie) Jed Alejæ Ko ciuszki; 0x233 PÚtle for KolejnÈ strukturÈ sterujÈcÈ jest pÚtla for, wykorzystywana wtedy, gdy programista chce, aby pÚtla wykonaïa okre lonÈ liczbÚ iteracji. Instrukcja dojazdu: „Jed niÈ jakie 8 kilometrów” przeksztaïcona do pÚtli for mogïaby wyglÈdaÊ nastÚpujÈco: For (8 iteracji) Jed prosto 1 kilometr; W rzeczywisto ci pÚtla for jest po prostu pÚtlÈ while z licznikiem. Powy szÈ instrukcjÚ mo na równie dobrze zapisaÊ tak: Ustaw licznik na 0 While (licznik jest mniejszy od 8) { Jed prosto 1 kilometr; Dodaj 1 do licznika; } Skïadnia pseudokodu dla pÚtli for sprawia, e jest to jeszcze bardziej widoczne: For (i=0; i<8; i++) Jed prosto 1 kilometr; W tym przypadku licznik nosi nazwÚ i, a instrukcja for jest podzielona na trzy sekcje oddzielone rednikami. Pierwsza sekcja deklaruje licznik i ustawia jego po- czÈtkowÈ warto Ê — w tym przypadku 0. Druga sekcja przypomina instrukcjÚ while z licznikiem — dopóki licznik speïnia podany warunek, kontynuuj pÚtlÚ. Trzecia i ostatnia sekcja opisuje, co ma siÚ dziaÊ z licznikiem przy ka dej iteracji. W tym przypadku i++ jest skróconym sposobem na powiedzenie: „Dodaj 1 do licznika o nazwie i”. Zastosowanie wszystkich omówionych struktur sterujÈcych umo liwia przeksztaï- cenie opisu dojazdu ze strony 6 w poni szy pseudokod przypominajÈcy jÚzyk C: Rozpocznij jazdú na wschód Alejæ Ko ciuszki; While (po prawej stronie nie ma ko cio a) Jed Alejæ Ko ciuszki; If (ulica zablokowana) { Skrúè w prawo w ul. Moniuszki); Skrúè w lewo w ul. Prusa); Skrúè w prawo w ul. Orzeszkowej); } Programowanie 25
  • 14. Else Skrúè(prawo, ul. Orzeszkowej); Skrúè(lewo, ul. Docelowa); For (i=0; i<8; i++) { Jed prosto 1 kilometr; } Zatrzymaj siú przy ul. Docelowej 743; 0x240 Podstawowe pojÚcia programistyczne W kolejnych punktach zostanÈ przedstawione podstawowe pojÚcia programistyczne. SÈ one wykorzystywane w wielu jÚzykach programowania, ró niÈ siÚ jedynie pod wzglÚdem syntaktycznym. Podczas prezentacji bÚdÈ integrowane z przykïadami w pseudokodzie przypominajÈcym skïadniÚ jÚzyka C. Na koñcu pseudokod bÚdzie bardzo przypominaï kod napisany w jÚzyku C. 0x241 Zmienne Licznik wykorzystywany w pÚtli for jest rodzajem zmiennej. O zmiennej mo emy my leÊ jak o obiekcie przechowujÈcym dane, które mogÈ byÊ zmieniane — stÈd nazwa. IstniejÈ równie zmienne, których warto ci nie sÈ zmieniane, i trafnie nazywa siÚ je staïymi. W przykïadzie motoryzacyjnym jako zmiennÈ mo emy potraktowaÊ prÚdko Ê samochodu, natomiast kolor lakieru samochodu byïby staïÈ. W pseudo- kodzie zmienne sÈ po prostu pojÚciami abstrakcyjnymi, natomiast w C (i wielu in- nych jÚzykach) zmienne przed wykorzystaniem muszÈ byÊ zadeklarowane i nale y okre liÊ ich typ. Jest tak dlatego, e program napisany w C bÚdzie kompilowany do postaci programu wykonywalnego. Podobnie jak przepis kucharski, w którym przed faktycznymi instrukcjami wymieniane sÈ wszystkie potrzebne skïadniki, de- klaracje zmiennych pozwalajÈ dokonaÊ przygotowañ przed przej ciem do faktycznej tre ci programu. Ostatecznie wszystkie zmienne sÈ przechowywane gdzie w pamiÚci, a ich deklaracje pozwalajÈ kompilatorowi wydajniej uporzÈdkowaÊ pamiÚÊ. Jednak na koniec, mimo wszystkich deklaracji typów zmiennych, wszystko odbywa siÚ w pamiÚci. W jÚzyku C dla ka dej zmiennej okre lany jest typ, opisujÈcy informacje, które bÚdÈ przechowywane w tej zmiennej. Do najczÚ ciej stosowanych typów zalicza- my int (liczby caïkowite), float (liczby zmiennoprzecinkowe) i char (pojedyncze znaki). Zmienne sÈ deklarowane poprzez u ycie tych sïów kluczowych przed nazwÈ zmiennej, co zobrazowano na poni szym przykïadzie. int a, b; float k; char z; Zmienne a i b sÈ zadeklarowane jako liczby caïkowite, k mo e przyjmowaÊ warto- ci zmiennoprzecinkowe (np. 3,14), a z powinna przechowywaÊ warto Ê znakowÈ, 26 0x200
  • 15. takÈ jak A lub w. Warto ci mo na przypisywaÊ zmiennym podczas deklaracji lub w dowolnym pó niejszym momencie. Sïu y do tego operator =. int a = 13, b; float k; char z = 'A'; k = 3.14; z = 'w'; b = a + 5; Po wykonaniu powy szych instrukcji zmienna a bÚdzie posiadaïa warto Ê 13, zmienna k bÚdzie zawieraïa liczbÚ 3,14, a zmienna b bÚdzie miaïa warto Ê 18, po- niewa 13 plus 5 równa siÚ 18. Zmienne sÈ po prostu sposobem pamiÚtania warto ci, jednak w jÚzyku C nale y najpierw zadeklarowaÊ typ ka dej zmiennej. 0x242 Operatory arytmetyczne Instrukcja b = a + 7 jest przykïadem bardzo prostego operatora arytmetycznego. W jÚzyku C dla ró nych operacji matematycznych wykorzystywane sÈ poni sze symbole. Pierwsze cztery operatory powinny wyglÈdaÊ znajomo. Redukcja modulo mo e stanowiÊ nowe pojÚcie, ale jest to po prostu reszta z dzielenia. Je eli a ma warto Ê 13, to 13 podzielone przez 5 równa siÚ 2, a reszta wynosi 3, co oznacza, e a % 5 = 3. Ponadto skoro zmienne a i b sÈ liczbami caïkowitymi, po wykonaniu instrukcji b = a / 5, zmienna b bÚdzie miaïa warto Ê 2, poniewa jest to czÚ Ê wyniku bÚdÈca liczbÈ caïkowitÈ. Do przechowania bardziej poprawnego wyniku, czyli 2,6, musi zostaÊ u yta zmienna typu float (zmiennoprzecinkowa). Operacja Symbol Przykïad Dodawanie + b = a + 5 Odejmowanie - b = a - 5 Mno enie * b = a * 5 Dzielenie / b = a / 5 Redukcja modulo % b = a % 5 Aby program korzystaï z tych zaïo eñ, musimy mówiÊ w jego jÚzyku. JÚzyk C dostarcza kilku skróconych form zapisu tych operacji arytmetycznych. Jedna z nich zostaïa przedstawiona wcze niej i jest czÚsto wykorzystywana w pÚtlach for. Peïne wyra enie Skrót Wyja nienie i = i + 1 i++ lub ++i Dodaje 1 do warto ci zmiennej. i = i - 1 i-- lub i-- Odejmuje 1 od warto ci zmiennej. Programowanie 27
  • 16. Te skrócone wyra enia mogÈ byÊ ïÈczone z innymi operacjami arytmetycznymi w celu utworzenia bardziej zïo onych wyra eñ. Wówczas staje siÚ widoczna ró nica miÚdzy i++ i ++i. Pierwsze wyra enie oznacza: „ZwiÚksz warto Ê i o 1 po przepro- wadzeniu operacji arytmetycznej”, natomiast drugie: „ZwiÚksz warto Ê i o 1 przed przeprowadzeniem operacji arytmetycznej”. Poni szy przykïad pozwoli to lepiej zrozumieÊ. int a, b; a = 5 b = a++ * 6; Po wykonaniu tego zestawu instrukcji zmienna b bÚdzie miaïa warto Ê 30, nato- miast zmienna a bÚdzie miaïa warto Ê 6, poniewa skrócony zapis b = a++ * 6 jest równowa ny poni szym instrukcjom. b = a * 6; a = a + 1; Je eli jednak zostanie u yta instrukcja b = ++a * 6, kolejno Ê dodawania zostanie zmieniona i otrzymamy odpowiednik poni szych instrukcji. a = a + 1; b = a * 6; Poniewa kolejno Ê wykonywania dziaïañ zmieniïa siÚ, w powy szym przypad- ku zmienna b bÚdzie miaïa warto Ê 36, natomiast warto Ê zmiennej a wciÈ bÚdzie wynosiïa 6. CzÚsto w programach musimy zmodyfikowaÊ zmiennÈ w danym miejscu. Przy- kïadowo mo emy dodaÊ dowolnÈ warto Ê, takÈ jak 12, i przechowaÊ wynik w tej samej zmiennej (np. i = i + 12) Zdarza siÚ to tak czÚsto, e równie utworzono skróconÈ formÚ tej instrukcji. Peïne wyra enie Skrót Wyja nienie i = i + 12 i+=12 Dodaje okre lonÈ warto Ê do warto ci zmiennej. i = i - 12 i-=12 Odejmuje okre lonÈ warto Ê od warto ci zmiennej. i = i * 12 i*=12 Mno y okre lonÈ warto Ê przez warto Ê zmiennej. i = i / 12 i/=12 Dzieli warto Ê zmiennej przez okre lonÈ warto Ê. 0x243 Operatory porównania Zmienne sÈ czÚsto wykorzystywane w instrukcjach warunkowych wcze niej opisanych struktur sterujÈcych, a te instrukcje warunkowe opierajÈ siÚ na jakiego rodzaju porównaniu. W jÚzyku C operatory porównania wykorzystujÈ skróconÈ skïadniÚ, która jest stosunkowo powszechna w innych jÚzykach programowania. 28 0x200
  • 17. Warunek Symbol Przykïad Mniejsze ni < (a < b) WiÚksze ni > (a < b) Mniejsze lub równe <= (a <= b) WiÚksze lub równe >= (a >= b) Równe == (a == b) Nie równa siÚ != (a != b) WiÚkszo Ê z tych operatorów jest zrozumiaïa, jednak e nale y zauwa yÊ, e w skrócie porównania równo ci wykorzystywane sÈ dwa znaki równo ci. Jest to wa ne rozró nienie, poniewa podwójny znak równo ci jest stosowany do sprawdzenia równo ci, natomiast jeden znak równo ci jest u ywany do przypisania warto ci zmiennej. Instrukcja a = 7 oznacza: „Umie Ê w zmiennej a warto Ê 7”, natomiast a == 7 oznacza: „Sprawd , czy warto Ê zmiennej a wynosi 7”. (Niektóre jÚzyki pro- gramowania, takie jak Pascal, wykorzystujÈ do przypisywania warto ci zmiennym nastÚpujÈcy znak — := — aby wyeliminowaÊ ryzyko bïÚdnego zrozumienia kodu). Nale y te zwróciÊ uwagÚ, e wykrzyknik zwykle oznacza nie. Ten symbol mo e byÊ wykorzystany do odwrócenia dowolnego wyra enia. !(a < b) jest równowa ne (a >= b) Operatory porównania mogÈ byÊ ïÈczone ze sobÈ za pomocÈ skrótów dla ope- ratorów logicznych OR i AND. Operator logiczny Symbol Przykïad OR || ((a < b) || (a < c)) AND && ((a < b) && !(a < c)) Przykïadowa instrukcja zawierajÈca dwa mniejsze warunki poïÈczone operato- rem OR zostanie oszacowana jako prawdziwa, je eli warto Ê zmiennej a bÚdzie mniej- sza od warto ci zmiennej b LUB warto Ê zmiennej a bÚdzie mniejsza od warto ci zmiennej c. Podobnie przykïadowa instrukcja zawierajÈca dwa mniejsze warunki poïÈczone operatorem AND zostanie oszacowana jako prawdziwa, je eli warto Ê zmiennej a bÚdzie mniejsza od warto ci zmiennej b I warto Ê zmiennej a nie bÚdzie mniejsza od warto ci zmiennej c. Takie instrukcje powinny byÊ grupowane za pomocÈ nawiasów i mogÈ zawieraÊ wiele ró nych odmian. Wiele rzeczy mo emy sprowadziÊ do zmiennych, operatorów porównania i struk- tur sterujÈcych. W przykïadzie myszy poszukujÈcej po ywienia gïód mo emy przed- stawiÊ jako zmiennÈ boolowskÈ o warto ci true lub false (prawda lub faïsz). Oczy- wi cie, 1 oznacza true, a 0 — false. Programowanie 29
  • 18. While (g ód == 1) { Szukaj po ywienia; Zjedz po ywienie; } Oto kolejny skrót czÚsto wykorzystywany przez programistów i hakerów. JÚzyk C nie zawiera adnych operatorów boolowskich, wiÚc ka da warto Ê niezerowa jest uznawana za true, a instrukcja jest szacowana jako false, gdy zawiera 0. W rzeczy- wisto ci operatory porównania faktycznie zwracajÈ 1, je eli porównanie jest speï- nione, a w przeciwnym przypadku zwracajÈ 0. Sprawdzenie, czy zmienna g ód ma warto Ê 1, zwróci 1, je eli g ód ma warto Ê 1, lub zwróci 0, je eli gïód ma warto Ê 0. Poniewa program wykorzystuje tylko te dwa przypadki, mo na w ogóle pominÈÊ operator porównania. While (g ód) { Szukaj po ywienia; Zjedz po ywienie; } Sprytniejszy program sterujÈcy zachowaniem myszy z u yciem wiÚkszej liczby danych wej ciowych to przykïad, jak mo na ïÈczyÊ operatory porównania ze zmien- nymi. While ((g ód) && !(kot_obecny)) { Szukaj po ywienia; If (!(po ywienie_znajduje_siú_w_pu apce_na_myszy; Zjedz po ywienie; } W tym przykïadzie zaïo ono, e dostÚpne sÈ równie zmienne opisujÈce obec- no Ê kota oraz poïo enie po ywienia z warto ciami 1 dla speïnienia warunku i 0 dla przypadku przeciwnego. Wystarczy pamiÚtaÊ, e warto Ê niezerowa oznacza prawdÚ, a warto Ê 0 jest szacowana jako faïsz. 0x244 Funkcje Czasami zdarzajÈ siÚ zestawy instrukcji, których programista bÚdzie potrzebowaï kilka razy. Takie instrukcje mo na zgrupowaÊ w mniejszym podprogramie, zwanym funkcjÈ. W innych jÚzykach funkcje nazywane sÈ tak e procedurami i podprocedu- rami. Przykïadowo wykonanie skrÚtu samochodem skïada siÚ z kilku mniejszych instrukcji: wïÈcz odpowiedni kierunkowskaz, zwolnij, sprawd , czy nie nadje d ajÈ inne samochody, skrÚÊ kierownicÚ w odpowiednim kierunku itd. Opis trasy z poczÈt- ku tego rozdziaïu zawieraï caïkiem sporo skrÚtów, jednak e wymienianie wszystkich 30 0x200
  • 19. drobnych instrukcji przy ka dym skrÚcie byïoby mudne (i zmniejszaïoby czytel- no Ê kodu). W celu zmodyfikowania sposobu dziaïania funkcji mo emy przesyïaÊ do niej zmienne jako argumenty. W tym przypadku do funkcji jest przesyïany kierunek skrÚtu. Function Skrút(zmienna_kierunku) { W æcz zmienna_kierunku kierunkowskaz; Zwolnij; Sprawd , czy nie nadje d ajæ inne samochody; while (nadje d ajæ inne samochody) { Zatrzymaj siú; Obserwuj nadje d ajæce samochody; } Obróè kierownicú w zmienna_kierunku; while (skrút nie jest uko czony) { if (prúdko è < 8 km/h) Przyspiesz; } Obróè kierownicú do pierwotnego po o enia; Wy æcz zmienna_kierunku kierunkowskaz; } Funkcja ta zawiera wszystkie instrukcje konieczne do wykonania skrÚtu. Gdy program, w którym funkcja taka siÚ znajduje, musi wykonaÊ skrÚt, mo e po prostu wywoïaÊ tÚ funkcjÚ. Gdy zostaje wywoïana, znajdujÈce siÚ w niej instrukcje sÈ wy- konywane z przesïanymi argumentami. NastÚpnie wykonywanie programu powraca do momentu za wywoïaniem funkcji. Do tej funkcji mo na przesïaÊ warto Ê lewo albo prawo, co spowoduje wykonanie skrÚtu w tym kierunku. Domy lnie w jÚzyku C funkcje mogÈ zwracaÊ warto ci do elementu wywoïujÈ- cego. Dla osób znajÈcych matematykÚ jest to zupeïnie zrozumiaïe. Wyobra my sobie funkcjÚ obliczajÈcÈ silniÚ — jest oczywiste, e zwraca wynik. W jÚzyku C funkcje nie sÈ oznaczane sïowem kluczowym function. Zamiast tego sÈ deklarowane przez typ danych zwracanej zmiennej. Taki format bardzo przy- pomina deklaracjÚ zmiennej. Je eli funkcja w zamierzeniu ma zwracaÊ liczbÚ caï- kowitÈ (mo e to byÊ np. funkcja obliczajÈca silniÚ jakiej liczby x), jej kod mógïby wyglÈdaÊ nastÚpujÈco: int factorial(int x) { int i; for(i=1; i < x; i++) x *= i; return x; } Programowanie 31
  • 20. Funkcja ta jest deklarowana liczbÈ caïkowitÈ, poniewa mno y ka dÈ warto Ê od 1 do x i zwraca wynik, który jest liczbÈ caïkowitÈ. Instrukcja return na koñcu funkcji przesyïa zawarto Ê zmiennej x i koñczy wykonywanie funkcji. FunkcjÚ obli- czajÈcÈ silniÚ mo na wówczas wykorzystaÊ jak ka dÈ zmiennÈ typu integer w gïównej czÚ ci ka dego programu, który „wie” o tej funkcji: int a=5, b; b = factorial(a); Po ukoñczeniu wykonywania tego krótkiego programu zmienna b bÚdzie miaïa warto Ê 120, poniewa funkcja factorial() zostanie wywoïana z argumentem 5 i zwróci 120. Ponadto w jÚzyku C kompilator musi „wiedzieÊ” o funkcji, zanim jej u yje. W tym celu mo na po prostu napisaÊ caïÈ funkcjÚ przed pó niejszym wykorzystaniem jej w programie lub skorzystaÊ z prototypu funkcji. Prototyp funkcji jest prostym spo- sobem poinformowania kompilatora, i powinien spodziewaÊ siÚ funkcji o podanej nazwie, zwracajÈcej okre lony typ danych i przyjmujÈcej argumenty o okre lonym typie danych. Faktyczny kod funkcji mo na umie ciÊ pod koniec programu, ale mo na jÈ wykorzystaÊ w dowolnym miejscu, poniewa kompilator bÚdzie ju wiedziaï o jej istnieniu. Przykïadowy prototyp funkcji factorial() mógïby wyglÈdaÊ nastÚpujÈco: int factorial(int); Zwykle prototypy funkcji sÈ umieszczane blisko poczÈtku programu. W proto- typie nie ma potrzeby definiowania nazw zmiennych, poniewa dzieje siÚ to w sa- mej funkcji. Kompilator musi jedynie znaÊ nazwÚ funkcji, typ zwracanych danych i typy danych argumentów funkcjonalnych. Je eli funkcja nie posiada warto ci, którÈ mo e zwróciÊ (np. wcze niej opisana funkcja skrúè()), powinna byÊ zadeklarowana jako typ void. Jednak e funkcja skrúè() nie posiada jeszcze caïej funkcjonalno ci wymaganej przez nasz opis dojazdu. Ka dy skrÚt w opisie dojazdu zawiera zarówno kierunek, jak i nazwÚ ulicy. To oznacza, e funkcja skrÚcajÈca powinna przyjmowaÊ dwie zmienne: kierunek skrÚtu oraz nazwÚ ulicy, w którÈ nale y skrÚciÊ. To komplikuje funkcjÚ skrÚcajÈcÈ, poniewa przed wykonaniem skrÚtu nale y zlokalizowaÊ ulicÚ. Bardziej kompletna funkcja skrÚcajÈca, w której wykorzystano skïadniÚ podobnÈ do jÚzyka C, jest zamieszczona w pseu- dokodzie poni szego listingu. void skrúè(zmienna_kierunku, nazwa_docelowej_ulicy) { Szukaj tabliczki z nazwæ ulicy; nazwa_bie æcego_skrzy owania = odczytaj tabliczkú z nazwæ ulicy; while (nazwa_bie æcego_skrzy owania != nazwa_docelowej_ulicy) { Szukaj innej tabliczki z nazwæ ulicy; nazwa_bie æcego_skrzy owania = odczytaj tabliczkú z nazwæ ulicy; } 32 0x200
  • 21. W æcz zmienna_kierunku kierunkowskaz; Zwolnij; Sprawd , czy nie nadje d ajæ inne samochody; while (nadje d ajæ inne samochody) { Zatrzymaj siú; Obserwuj nadje d ajæce samochody; } Obróè kierownicú w zmienna_kierunku; while (skrút nie jest uko czony) { if (prúdko è < 8 km/h) Przyspiesz; } Obróè kierownicú do pierwotnego po o enia; Wy æcz zmienna_kierunku kierunkowskaz; } Funkcja ta zawiera sekcjÚ, która wyszukuje odpowiednie skrzy owanie poprzez odnajdywanie tabliczki z nazwÈ ulicy, odczytywanie z niej nazwy i przechowywanie jej w zmiennej o nazwie nazwa_bie æcego_skrzy owania. Wyszukiwanie i odczyty- wanie tabliczek z nazwami odbywa siÚ do momentu odnalezienia docelowej ulicy. Wówczas wykonywane sÈ pozostaïe instrukcje skrÚtu. Mo emy teraz zmieniÊ pseu- dokod z instrukcjami dojazdu, aby wykorzystywaï funkcjÚ skrÚtu. Rozpocznij jazdú na wschód Alejæ Ko ciuszki; while (po prawej stronie nie ma ko cio a) { Jed Alejæ Ko ciuszki; } If (ulica zablokowana) { Skrúè(prawo, ul. Moniuszki); Skrúè(lewo, ul. Prusa); Skrúè(prawo, ul. Orzeszkowej); } else { Skrúè(prawo, ul. Orzeszkowej); } Skrúè(lewo, ul. Docelowa); For (i=0; i<5; i++) { Jed prosto 1 kilometr; } Zatrzymaj siú przy ul. Docelowej 743; Funkcje nie sÈ czÚsto wykorzystywane w pseudokodzie, bo zwykle jest on sto- sowany przez programistów do zarysowania zaïo eñ programu przed napisaniem kompilowalnego kodu. Poniewa pseudokod nie musi dziaïaÊ, nie trzeba wypisywaÊ peïnych funkcji — wystarczy jedynie krótki zapisek: Tu zrób co zïo onego. Jednak Programowanie 33
  • 22. w jÚzyku programowania, takim jak C, funkcje sÈ czÚsto wykorzystywane. WiÚkszo Ê prawdziwej u yteczno ci C pochodzi ze zbiorów istniejÈcych funkcji, zwanych bibliotekami. 0x250 Zaczynamy brudziÊ sobie rÚce Gdy zaznajomili my siÚ ju trochÚ ze skïadniÈ jÚzyka C i wyja nili my kilka pod- stawowych pojÚÊ programistycznych, przej cie do faktycznego programowania w C nie jest niczym nadzwyczajnym. Kompilatory jÚzyka C istniejÈ dla niemal ka dego systemu operacyjnego i architektury procesora, jednak w niniejszej ksiÈ ce bÚdziemy wykorzystywali wyïÈcznie system Linux i procesor z rodziny x86. Linux jest dar- mowym systemem operacyjnym, do którego ka dy ma dostÚp, a procesory x86 sÈ najpopularniejszymi procesorami konsumenckimi na wiecie. Poniewa hacking wiÈ e siÚ gïównie z eksperymentowaniem, najlepiej bÚdzie, je eli w trakcie lektury bÚdziesz dysponowaï kompilatorem jÚzyka C. DziÚki dyskowi LiveCD doïÈczonemu do niniejszej ksiÈ ki mo esz praktycznie stosowaÊ przekazywane informacje, je eli tylko dysponujesz procesorem z rodziny x86. Wystarczy wïo yÊ dysk CD do napÚdu i ponownie uruchomiÊ komputer. Uru- chomione zostanie rodowisko linuksowe, które nie narusza istniejÈcego systemu ope- racyjnego. W tym rodowisku mo esz wypróbowywaÊ przykïady z ksiÈ ki, a tak e przeprowadzaÊ wïasne eksperymenty. Przejd my do rzeczy. Program firstprog.c jest prostym fragmentem kodu w C, wypisujÈcym 10 razy „Hello world!”. Listing 2.1. firstprog.c #include <stdio.h> int main() { int i; for(i=0; i < 10; i++) // Wykonaj pútlú 10 razy. { puts("Hello, world!n"); // Przeka a cuch do wyj cia. } return 0; // Poinformuj OS, e program zako czy siú bez b údów. } Gïówne wykonywanie programu napisanego w C rozpoczyna siÚ w funkcji main(). Tekst znajdujÈcy siÚ za dwoma uko nikami jest komentarzem ignorowanym przez kompilator. Pierwszy wiersz mo e wprawiaÊ w zakïopotanie, ale jest to jedynie skïadnia informujÈca kompilator, aby doïÈczyï nagïówki dla standardowej biblioteki wej- cia-wyj cia o nazwie stdio. Ten plik nagïówkowy jest dodawany do programu podczas kompilacji. Znajduje siÚ on w /usr/include/stdio.h i definiuje kilka staïych i prototypów funkcji dla odpowiednich funkcji w standardowej bibliotece we-wy. Poniewa funkcja main() wykorzystuje funkcjÚ printf() ze standardowej biblioteki 34 0x200
  • 23. we-wy, wymagany jest prototyp funkcji printf() przed jej zastosowaniem. Ten prototyp funkcji (a tak e wiele innych) znajduje siÚ w pliku nagïówkowym stdio.h. Sporo mo liwo ci jÚzyka C to pochodne jego zdolno ci do rozbudowy oraz wyko- rzystania bibliotek. Reszta kodu powinna byÊ zrozumiaïa i przypomina wcze niej prezentowany pseudokod. SÈ nawet nawiasy klamrowe, które mo na byïo pominÈÊ. To, co bÚdzie siÚ dziaïo po uruchomieniu tego programu, powinno byÊ oczywiste, ale skompilujmy go za pomocÈ GCC, aby siÚ upewniÊ. GNU Compiler Collection jest darmowym kompilatorem jÚzyka C, tïumaczÈcym jÚzyk C na jÚzyk maszynowy, zrozumiaïy dla komputera. W wyniku tïumaczenia powstaje wykonywalny plik binarny, któremu domy lnie nadawana jest nazwa a.out. Czy skompilowany program wykonuje to, co chcieli my? reader@hacking:~/booksrc $ gcc firstprog.c reader@hacking:~/booksrc $ ls -l a.out -rwxr-xr-x 1 reader reader 6621 2007-09-06 22:16 a.out reader@hacking:~/booksrc $ ./a.out Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! reader@hacking:~/booksrc $ 0x251 WiÚkszy obraz Dobrze, tego wszystkiego mo na siÚ nauczyÊ na podstawowym kursie programo- wania — sÈ to podstawy, ale niezbÚdne. WiÚkszo Ê poczÈtkowych kursów progra- mowania uczy jedynie, jak czytaÊ i pisaÊ w jÚzyku C. ProszÚ mnie le nie zrozumieÊ — pïynna znajomo Ê C jest bardzo przydatna i wystarczy do stania siÚ dobrym programistÈ, ale jest to tylko czÚ Ê wiÚkszej caïo ci. WiÚkszo Ê programistów uczy siÚ jÚzyka z góry do doïu i nigdy nie ma szerszego obrazu. Hakerzy sÈ tak dobrzy, poniewa wiedzÈ, jak wszystkie czÚ ci tego wiÚkszego obrazu wchodzÈ ze sobÈ w interakcje. Aby w programowaniu patrzeÊ szerzej, wystarczy sobie zdaÊ sprawÚ, e kod w jÚzyku C bÚdzie kompilowany. Kod nie mo e nic zrobiÊ, dopóki nie zostanie skompilowany do wykonywalnego pliku binarnego. My lenie o kodzie ródïowym w C jak o programie jest czÚstym bïÚdem wykorzystywanym codziennie przez ha- kerów. Instrukcje w pliku a.out sÈ zapisane w jÚzyku maszynowym — podstawowym jÚzyku zrozumiaïym dla procesora. Kompilatory tïumaczÈ jÚzyk kodu C na jÚzyk maszynowy ró nych architektur procesorów. W tym przypadku procesor pocho- dzi z rodziny wykorzystujÈcej architekturÚ x86. IstniejÈ równie architektury pro- cesorów Sparc (u ywane w stacjach roboczych Sun) oraz architektura PowerPC Programowanie 35
  • 24. (wykorzystywana w macintoshach przed zastosowaniem procesorów Intela). Ka da architektura wymaga innego jÚzyka maszynowego, wiÚc kompilator jest po redni- kiem — tïumaczy kod w jÚzyku C na jÚzyk maszynowy docelowej architektury. Dopóki skompilowany program dziaïa, przeciÚtny programista skupia siÚ wy- ïÈcznie na kodzie ródïowym. Jednak haker zdaje sobie sprawÚ, e w rzeczywisto ci wykonywany jest program skompilowany. MajÈc dogïÚbnÈ wiedzÚ na temat dziaïania procesora, haker mo e manipulowaÊ dziaïajÈcymi programami. Widzieli my kod ródïowy naszego pierwszego programu i skompilowali my go do pliku wykony- walnego dla architektury x86. Ale jak wyglÈda ten wykonywalny plik binarny? Na- rzÚdzia programistyczne GNU zawierajÈ program o nazwie objdump, który mo e byÊ u yty do badania skompilowanych plików binarnych. Rozpocznijmy od poznania kodu maszynowego, na który zostaïa przetïumaczona funkcja main(). reader@hacking:~/booksrc $ objdump -D a.out | grep -A20 main.: 08048374 <main>: 8048374: 55 push %ebp 8048375: 89 e5 mov %esp,%ebp 8048377: 83 ec 08 sub $0x8,%esp 804837a: 83 e4 f0 and $0xfffffff0,%esp 804837d: b8 00 00 00 00 mov $0x0,%eax 8048382: 29 c4 sub %eax,%esp 8048384: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp) 804838b: 83 7d fc 09 cmpl $0x9,0xfffffffc(%ebp) 804838f: 7e 02 jle 8048393 <main+0x1f> 8048391: eb 13 jmp 80483a6 <main+0x32> 8048393: c7 04 24 84 84 04 08 movl $0x8048484,(%esp) 804839a: e8 01 ff ff ff call 80482a0 <printf@plt> 804839f: 8d 45 fc lea 0xfffffffc(%ebp),%eax 80483a2: ff 00 incl (%eax) 80483a4: eb e5 jmp 804838b <main+0x17> 80483a6: c9 leave 80483a7: c3 ret 80483a8: 90 nop 80483a9: 90 nop 80483aa: 90 nop reader@hacking:~/booksrc $ Program objdump zwróciï zbyt wiele wierszy wynikowych, aby rozsÈdnie siÚ im przyjrzeÊ, wiÚc przekazali my wyj cie do grep z opcjÈ powodujÈcÈ wy wietlenie tylko 20 wierszy za wyra eniem regularnym main.:. Ka dy bajt jest reprezentowany w notacji szesnastkowej, systemie liczbowym o podstawie 16. System liczbowy, do którego jeste my najbardziej przyzwyczajeni, wykorzystuje podstawÚ 10, a przy liczbie 10 nale y umie ciÊ dodatkowy symbol. W systemie szesnastkowym stoso- wane sÈ cyfry od 0 do 9 reprezentujÈce 0 do 9, ale tak e litery A do F, które repre- zentujÈ w nim liczby od 10 do 15. Jest to wygodny zapis, poniewa bajt zawiera 8 bi- tów, z których ka dy mo e mieÊ warto Ê prawda lub faïsz. To oznacza, e bajt ma 256 (28) mo liwych warto ci, wiÚc ka dy bajt mo e byÊ opisany za pomocÈ dwóch cyfr w systemie szesnastkowym. 36 0x200
  • 25. Liczby szesnastkowe — rozpoczynajÈc od 0x8048374 po lewej stronie — sÈ ad- resami pamiÚci. Bity jÚzyka maszynowego muszÈ byÊ gdzie przechowywane, a tym „gdzie ” jest pamiÚÊ. PamiÚÊ jest po prostu zbiorem bajtów z tymczasowej przestrzeni magazynowej, którym przypisano adresy liczbowe. Podobnie jak rzÈd domów przy lokalnej ulicy, z których ka dy posiada wïasny adres, pamiÚÊ mo emy traktowaÊ jako rzÈd bajtów, z których ka dy ma wïasny adres. Do ka dego bajta pamiÚci mo na uzyskaÊ dostÚp za pomocÈ jego adresu, a w tym przypadku procesor siÚga do tej czÚ ci pamiÚci, aby pobraÊ instrukcje jÚzyka ma- szynowego skïadajÈce siÚ na skompilowany program. Starsze procesory Intela z rodzi- ny x86 wykorzystujÈ 32-bitowy schemat adresacji, natomiast nowsze — 64-bitowy. Procesory 32-bitowe posiadajÈ 232 (lub te 4 294 967 296) mo liwych adresów, na- tomiast procesory 64-bitowe dysponujÈ ilo ciÈ adresów równÈ 264 (1,84467441 × 1019). Procesory 64-bitowe mogÈ pracowaÊ w trybie kompatybilno ci 32-bitowej, co umo - liwia im szybkie wykonywanie kodu 32-bitowego. Bajty szesnastkowe znajdujÈce siÚ po rodku powy szego listingu sÈ instrukcjami w jÚzyku maszynowym procesora x86. Oczywi cie, te warto ci szesnastkowe sÈ jedynie reprezentacjami binarnych jedynek i zer, które rozumie procesor. Ale po- niewa 0101010110001001111001011000001111101100111100001… przydaje siÚ tylko procesorowi, kod maszynowy jest wy wietlany jako bajty szesnastkowe, a ka da instrukcja jest umieszczana w osobnym wierszu, co przypomina podziaï akapitu na zdania. Gdy siÚ zastanowimy, oka e siÚ, e bajty szesnastkowe same w sobie te nie sÈ przydatne — tutaj dochodzi do gïosu jÚzyk asembler. Instrukcje po prawej stronie sÈ zapisane w asemblerze. Asembler jest po prostu zbiorem mnemoników dla od- powiednich instrukcji jÚzyka maszynowego. Instrukcja ret jest znacznie ïatwiejsza do zapamiÚtania i zrozumienia ni 0xc3 czy te 11000011. W przeciwieñstwie do C i innych jÚzyków kompilowanych, instrukcje asemblera wystÚpujÈ w relacji jeden- do-jednego z instrukcjami odpowiednimi jÚzyka maszynowego. Oznacza to, e skoro ka da architektura procesora posiada wïasny zestaw instrukcji jÚzyka maszynowego, ka da z nich ma równie wïasnÈ odmianÚ asemblera. JÚzyk asemblera jest dla pro- gramistów tylko sposobem reprezentacji instrukcji jÚzyka maszynowego podawa- nych procesorowi. Dokïadny sposób reprezentacji tych instrukcji maszynowych jest tylko kwestiÈ konwencji i preferencji. ChoÊ teoretycznie mo na stworzyÊ wïasnÈ skïadniÚ asemblera dla architektury x86, wiÚkszo Ê osób wykorzystuje jeden z gïów- nych typów — skïadniÚ AT&T lub Intel. Kod asemblera przedstawiony na stronie 21 jest zgodny ze skïadniÈ AT&T, poniewa niemal wszystkie dezasemblery w Linuksie domy lnie wykorzystujÈ tÚ skïadniÚ. SkïadniÚ AT&T mo na ïatwo rozpoznaÊ dziÚ- ki kakofonii symboli % i $ umieszczanych przed wszystkimi elementami (proszÚ ponownie spojrzeÊ na stronÚ 21). Ten sam kod mo na wy wietliÊ w skïadni Intela, dodajÈc do polecenia objdump dodatkowÈ opcjÚ -M: reader@hacking:~/booksrc $ objdump -M intel -D a.out | grep -A20 main.: 08048374 <main>: 8048374: 55 push ebp 8048375: 89 e5 mov ebp,esp Programowanie 37
  • 26. 8048377: 83 ec 08 sub esp,0x8 804837a: 83 e4 f0 and esp,0xfffffff0 804837d: b8 00 00 00 00 mov eax,0x0 8048382: 29 c4 sub esp,eax 8048384: c7 45 fc 00 00 00 00 mov DWORD PTR [ebp-4],0x0 804838b: 83 7d fc 09 cmp DWORD PTR [ebp-4],0x9 804838f: 7e 02 jle 8048393 <main+0x1f> 8048391: eb 13 jmp 80483a6 <main+0x32> 8048393: c7 04 24 84 84 04 08 mov DWORD PTR [esp],0x8048484 804839a: e8 01 ff ff ff call 80482a0 <printf@plt> 804839f: 8d 45 fc lea eax,[ebp-4] 80483a2: ff 00 inc DWORD PTR [eax] 80483a4: eb e5 jmp 804838b <main+0x17> 80483a6: c9 leave 80483a7: c3 ret 80483a8: 90 nop 80483a9: 90 nop 80483aa: 90 nop reader@hacking:~/booksrc $ Uwa am, e skïadnia Intela jest znacznie bardziej czytelna i ïatwiejsza do zro- zumienia, wiÚc bÚdzie ona stosowana w niniejszej ksiÈ ce. Niezale nie od repre- zentacji jÚzyka asemblera, polecenia rozumiane przez procesor sÈ caïkiem proste. Instrukcje te skïadajÈ siÚ z operacji i czasem dodatkowych operacji opisujÈcych cel i (lub) ródïo operacji. Operacje te przenoszÈ dane w pamiÚci, aby wykonaÊ jakie- go rodzaju podstawowe dziaïania matematyczne, lub przerywajÈ dziaïanie proce- sora, by wykonaÊ co innego. To jest wszystko, co procesor potrafi wykonaÊ. Jednak, podobnie jak za pomocÈ stosunkowo niewielkiego alfabetu napisano miliony ksiÈ ek, tak samo, korzystajÈc z niewielkiego zbioru instrukcji maszynowych, mo na utworzyÊ nieskoñczenie wiele programów. Procesory posiadajÈ równie wïasny zestaw specjalnych zmiennych zwanych rejestrami. WiÚkszo Ê instrukcji wykorzystuje rejestry do odczytywania lub zapi- sywania danych, wiÚc ich poznanie jest niezbÚdne do zrozumienia instrukcji. Du y obraz wciÈ siÚ powiÚksza… 0x252 Procesor x86 Procesor 8086 byï pierwszym procesorem w architekturze x86. Zostaï opracowany i wyprodukowany przez firmÚ Intel, która pó niej wprowadzaïa na rynek bardziej zaawansowane procesory z tej rodziny: 80186, 80286m 80386 i 80486. Je eli pamiÚ- tasz, e w latach 80. i 90. ubiegïego wieku mówiono o procesorach 386 i 486, chodziïo wówczas o te wïa nie ukïady. Procesor x86 posiada kilka rejestrów, które sÈ dla niego czym w rodzaju we- wnÚtrznych zmiennych. Mógïbym teraz przeprowadziÊ abstrakcyjny wykïad na temat rejestrów, ale uwa am, e lepiej zobaczyÊ co na wïasne oczy. NarzÚdzia progra- mistyczne GNU zawierajÈ równie debuger o nazwie GDB. Debugery sÈ u ywane przez programistów do wykonywania skompilowanych programów krok po kroku, badania pamiÚci programu i przeglÈdania rejestrów procesora. Programista, który 38 0x200
  • 27. nigdy nie korzystaï z debugera do przyjrzenia siÚ wewnÚtrznym mechanizmom pracy programu, jest jak siedemnastowieczny badacz, który nigdy nie u ywaï mi- kroskopu. Debuger, tak jak mikroskop, pozwala hakerowi na precyzyjne przyjrze- nie siÚ kodowi maszynowemu, ale mo liwo ci debugera wykraczajÈ daleko poza tÚ metaforÚ. W przeciwieñstwie do mikroskopu, debuger umo liwia obejrzenie wy- konywania programu ze wszystkich stron, wstrzymanie go oraz zmianÚ wszelkich parametrów. Poni ej GDB zostaï u yty do wy wietlenia stanu rejestrów procesora tu przed rozpoczÚciem programu: reader@hacking:~/booksrc $ gdb -q ./a.out Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1". (gdb) break main Breakpoint 1 at 0x804837a (gdb) run Starting program: /home/reader/booksrc/a.out Breakpoint 1, 0x0804837a in main () (gdb) info registers eax 0xbffff894 -1073743724 ecx 0x48e0fe81 1222704769 edx 0x1 1 ebx 0xb7fd6ff4 -1208127500 esp 0xbffff800 0xbffff800 ebp 0xbffff808 0xbffff808 esi 0xb8000ce0 -1207956256 edi 0x0 0 eip 0x804837a 0x804837a <main+6> eflags 0x286 [ PF SF IF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb) quit The program is running. Exit anyway? (y or n) y reader@hacking:~/booksrc $ Punkt wstrzymania zostaï ustawiony przy funkcji main(), wiÚc wykonywanie programu zostanie zatrzymane tu przed uruchomieniem naszego kodu. NastÚpnie GDB uruchamia program, zatrzymuje siÚ w punkcie wstrzymania i wy wietla wszyst- kie rejestry procesora i ich bie Ècy stan. Pierwsze cztery rejestry (EAX, ECX, EDX i EBX) sÈ rejestrami ogólnego prze- znaczenia. SÈ to odpowiednio rejestry: akumulatorowy, licznika, danych i bazowy. SÈ one wykorzystywane do ró nych celów, ale sïu È gïównie jako zmienne tymcza- sowe dla procesora, gdy wykonuje instrukcje kodu maszynowego. Programowanie 39
  • 28. Kolejne cztery rejestry (ESP, EBP, ESI i EDI) sÈ równie rejestrami ogólnego przeznaczenia, ale czasem nazywa siÚ je wska nikami i indeksami. SÈ to odpowiednio: wska nik, wska nik bazowy, ródïo i przeznaczenie. Pierwsze dwa rejestry sÈ nazy- wane wska nikami, poniewa przechowujÈ 32-bitowe adresy, wskazujÈce do miejsc w pamiÚci. Te rejestry sÈ istotne dla wykonywania programu i zarzÈdzania pamiÚciÈ. Pó niej omówiÚ je dokïadniej. Kolejne dwa rejestry, z technicznego punktu widzenia równie wska nikowe, czÚsto wykorzystywane sÈ do wskazywania ródïa i celu, gdy dane muszÈ byÊ odczytane lub zapisane. IstniejÈ instrukcje odczytujÈce i zapisujÈce, które u ywajÈ tych rejestrów, ale przewa nie mo na je traktowaÊ jak zwykïe rejestry ogólnego przeznaczenia. Rejestr EIP jest rejestrem wska nika instrukcji, wskazujÈcym aktualnie wykony- wanÈ instrukcjÚ. Tak jak dziecko podczas czytania pokazuje sobie palcem poszczegól- ne sïowa, tak procesor odczytuje konkretne instrukcje, korzystajÈc z EIP jak z palca. Oczywi cie, rejestr ten jest bardzo istotny i bÚdzie czÚsto wykorzystywany podczas debugowania. Aktualnie wskazuje adres pamiÚci 0x804838a. Pozostaïy rejestr, EFLAGS, zawiera kilka flag bitowych wykorzystywanych do porównañ oraz segmentacji pamiÚci. PamiÚÊ jest dzielona na kilka ró nych seg- mentów, co opiszÚ pó niej, a rejestr ten pozwala je ledziÊ. Przewa nie mo emy je zignorowaÊ, poniewa rzadko konieczny jest bezpo redni dostÚp do nich. 0x253 JÚzyk asembler Poniewa w niniejszej ksiÈ ce wykorzystujemy skïadniÚ Intela w jÚzyku asembler, musimy odpowiednio skonfigurowaÊ narzÚdzia. W GDB skïadniÚ dezasemblera mo na ustawiÊ na intelowskÈ, wpisujÈc po prostu set disassembly intel lub w skrócie set dis intel. Mo emy skonfigurowaÊ GDB tak, aby to ustawienie byïo aktywne przy ka dym uruchomieniu, umieszczajÈc to polecenie w pliku .gdbinit w katalogu domowym. reader@hacking:~/booksrc $ gdb -q (gdb) set dis intel (gdb) quit reader@hacking:~/booksrc $ echo "set dis intel" > ~/.gdbinit reader@hacking:~/booksrc $ cat ~/.gdbinit set dis intel reader@hacking:~/booksrc $ Po skonfigurowaniu GDB tak, eby wykorzystywaï skïadniÚ Intela, zapoznajmy siÚ z niÈ. W skïadni Intela instrukcje asemblera majÈ zwykle poni szÈ postaÊ: operacja <cel>, < ród o> Warto ciami docelowymi i ródïowymi sÈ rejestr, adres pamiÚci lub warto Ê. Operacje sÈ zwykle intuicyjnie rozumianymi mnemonikami. Operacja mov przenosi warto Ê ze ródïa do celu, sub odejmuje, inc inkrementuje itd. Przykïadowo poni sze instrukcje przenoszÈ warto Ê z ESP do EBP, a nastÚpnie odejmujÈ 8 od ESP (zapisu- jÈc wynik w ESP). 40 0x200
  • 29. 8048375: 89 e5 mov ebp,esp 8048377: 83 ec 08 sub esp,0x8 DostÚpne sÈ równie operacje wykorzystywane do sterowanie przebiegiem wykonywania. Operacja cmp sïu y do porównywania warto ci, a niemal wszystkie operacje, których nazwa rozpoczyna siÚ literÈ j, sïu È do przeskakiwania do innej czÚ ci kodu (w zale no ci od wyniku porównania). W poni szym przykïadzie najpierw 4-bajtowa warto Ê znajdujÈca w ERB minus 4 jest porównywana z liczbÈ 9. NastÚpna instrukcja jest skrótem od przeskocz, je eli mniejsze lub równe ni (ang. jump if less than or equal to), odnoszÈcym siÚ do wyniku wcze niejszego porównania. Je eli warto Ê ta jest mniejsza lub równa 9, wykonywanie przeskoczy do instrukcji znaj- dujÈcej siÚ pod adresem 0x8048393. W przeciwnym przypadku wykonywana bÚdzie kolejna instrukcja z bezwarunkowym przeskokiem. Je eli warto Ê nie bÚdzie mniejsza ani równa 9, procesor przeskoczy do 0x80483a6. 804838b: 83 7d fc 09 cmp DWORD PTR [ebp-4],0x9 804838f: 7e 02 jle 8048393 <main+0x1f> 8048391: eb 13 jmp 80483a6 <main+0x32> Przykïady te pochodzÈ z naszej poprzedniej dezasemblacji. Skonfigurowali my debuger do wykorzystywania skïadni Intela, wiÚc wykorzystajmy go do kroczenia przez nasz pierwszy program na poziomie instrukcji asemblera. W kompilatorze GCC mo na podaÊ opcjÚ –g, dziÚki czemu zostanÈ doïÈczone dodatkowe informacje debugowania, co da GDB dostÚp do kodu ródïowego. reader@hacking:~/booksrc $ gcc -g firstprog.c reader@hacking:~/booksrc $ ls -l a.out -rwxr-xr-x 1 matrix users 11977 Jul 4 17:29 a.out reader@hacking:~/booksrc $ gdb -q ./a.out Using host libthread_db library "/lib/libthread_db.so.1". (gdb) list 1 #include <stdio.h> 2 3 int main() 4 { 5 int i; 6 for(i=0; i < 10; i++) 7 { 8 printf("Hello, world!n"); 9 } 10 } (gdb) disassemble main Dump of assembler code for function main(): 0x08048384 <main+0>: push ebp 0x08048385 <main+1>: mov ebp,esp 0x08048387 <main+3>: sub esp,0x8 0x0804838a <main+6>: and esp,0xfffffff0 0x0804838d <main+9>: mov eax,0x0 0x08048392 <main+14>: sub esp,eax Programowanie 41
  • 30. 0x08048394 <main+16>: mov DWORD PTR [ebp-4],0x0 0x0804839b <main+23>: cmp DWORD PTR [ebp-4],0x9 0x0804839f <main+27>: jle 0x80483a3 <main+31> 0x080483a1 <main+29>: jmp 0x80483b6 <main+50> 0x080483a3 <main+31>: mov DWORD PTR [esp],0x80484d4 0x080483aa <main+38>: call 0x80482a8 <_init+56> 0x080483af <main+43>: lea eax,[ebp-4] 0x080483b2 <main+46>: inc DWORD PTR [eax] 0x080483b4 <main+48>: jmp 0x804839b <main+23> 0x080483b6 <main+50>: leave 0x080483b7 <main+51>: ret End of assembler dump. (gdb) break main Breakpoint 1 at 0x8048394: file firstprog.c, line 6. (gdb) run Starting program: /hacking/a.out Breakpoint 1, main() at firstprog.c:6 6 for(i=0; i < 10; i++) (gdb) info register eip eip 0x8048394 0x8048394 (gdb) Najpierw wypisywany jest kod ródïowy oraz dezasemblacja funkcji main(). NastÚpnie na poczÈtku main() ustawiany jest punkt wstrzymania i program jest uruchamiany. Ten punkt wstrzymania po prostu informuje debuger, aby wstrzymaï wykonywanie programu, gdy dojdzie do tego punktu. Poniewa punkt wstrzymania zostaï ustawiony na poczÈtku funkcji main(), program dociera do punktu wstrzy- mania i zatrzymuje siÚ przed wykonaniem jakichkolwiek instrukcji z funkcji main(). NastÚpnie wy wietlana jest warto Ê EIP (wska nika instrukcji). Nale y zwróciÊ uwagÚ, e EIP zawiera adres pamiÚci, wskazujÈcy instrukcjÚ w dezasemblacji funkcji main() (pogrubionej na listingu). Wcze niejsze instrukcje (zapisane kursywÈ), razem nazywane prologiem funkcji, sÈ generowane przez kom- pilator w celu ustawienia pamiÚci dla reszty zmiennych lokalnych funkcji main(). Jednym z powodów konieczno ci deklaracji zmiennych w jÚzyku C jest pomoc w konstrukcji tej czÚ ci kodu. Debuger „wie”, e ta czÚ Ê kodu jest generowana automatycznie i potrafi jÈ pominÈÊ. Prologiem funkcji zajmiemy siÚ pó niej, a na razie, wzorujÈc siÚ na GDB, pominiemy go. Debuger GDB zawiera bezpo redniÈ metodÚ badania pamiÚci za pomocÈ pole- cenia x, które jest skrótem od examine. Badanie pamiÚci jest bardzo wa nÈ umiejÚtno- ciÈ ka dego hakera. WiÚkszo Ê technik hakerskich przypomina sztuczki magiczne — wydajÈ siÚ niesamowite i magiczne, dopóki nie poznasz oszustwa. Zarówno w magii, jak i hakerstwie, je eli popatrzymy w odpowiednie miejsce, sztuczka stanie siÚ oczywista. Jest to jeden z powodów, dla których dobry magik nigdy nie wykonuje dwa razy tego samego triku w czasie jednego wystÚpu. Jednak za pomocÈ debugera, takiego jak GDB, mo emy dokïadnie zbadaÊ ka dy aspekt wykonywania programu, wstrzymaÊ go, przej Ê krok dalej i powtórzyÊ tyle razy, ile potrzeba. Poniewa dziaïajÈcy program to w wiÚkszo ci procesor i segmenty pamiÚci, zbadanie pamiÚci jest pierwszÈ z metod przekonania siÚ, co naprawdÚ siÚ dzieje. 42 0x200
  • 31. Polecenie examine w GDB mo e zostaÊ u yte do przyjrzenia siÚ okre lonym adre- som pamiÚci na ró ne sposoby. To polecenie oczekuje dwóch argumentów: miejsca w pamiÚci, które ma byÊ zbadane, oraz okre lenia sposobu wy wietlania zawarto ci. Do okre lania formatu wy wietlania równie u ywany jest jednoliterowy skrót, który mo na poprzedziÊ liczbÈ elementów do zbadania. NajczÚ ciej wykorzystywane sÈ poni sze skróty formatujÈce: o — wy wietla w formacie ósemkowym, x — wy wietla w formacie szesnastkowym, u — wy wietla w standardowym systemie dziesiÚtnym, bez znaków, t — wy wietla w formacie binarnym. Liter tych mo na u yÊ z poleceniem examine do zbadania okre lonego adresu pamiÚci. W poni szym przykïadzie wykorzystano bie Ècy adres z rejestru EIP. Skrócone polecenia sÈ czÚsto wykorzystywane w GDB i nawet info register eip mo na skróciÊ do i r eip. (gdb) i r eip eip 0x8048384 0x8048384 <main+16> (gdb) x/o 0x8048384 0x8048384 <main+16>: 077042707 (gdb) x/x $eip 0x8048384 <main+16>: 0x00fc45c7 (gdb) x/u $eip 0x8048384 <main+16>: 16532935 (gdb) x/t $eip 0x8048384 <main+16>: 00000000111111000100010111000111 (gdb) PamiÚÊ, którÈ wskazuje rejestr EIP, mo e byÊ zbadana za pomocÈ adresu prze- chowywanego w EIP. Debuger umo liwia bezpo rednie odwoïywanie siÚ do reje- strów, wiÚc $eip jest równowa ne warto ci przechowywanej aktualnie w EIP. Warto Ê 077042707 w systemie ósemkowym jest tym samym, co 0x00fc45c7 w systemie szes- nastkowym, co jest tym samym, co 16532935 w systemie dziesiÚtnym, co z kolei jest tym samym, co 00000000111111000100010111000111 w systemie dwójkowym. Format polecenia examine mo na równie poprzedziÊ cyfrÈ, okre lajÈcÈ liczbÚ badanych jednostek w docelowym adresie. (gdb) x/2x $eip 0x8048384 <main+16>: 0x00fc45c7 0x83000000 (gdb) x/12x $eip 0x8048384 <main+16>: 0x00fc45c7 0x83000000 0x7e09fc7d 0xc713eb02 0x8048394 <main+32>: 0x84842404 0x01e80804 0x8dffffff 0x00fffc45 0x80483a4 <main+48>: 0xc3c9e5eb 0x90909090 0x90909090 0x5de58955 (gdb) Programowanie 43
  • 32. Domy lnym rozmiarem jednej jednostki jest 4-bajtowa jednostka zwana sïowem. Rozmiar jednostek wy wietlania dla polecenia examine mo e byÊ zmieniany poprzez dodanie odpowiedniej litery za literÈ formatujÈcÈ. Poprawnymi literami rozmiaru sÈ: b — pojedynczy bajt, h — póïsïowo o rozmiarze dwóch bajtów, w — sïowo o rozmiarze czterech bajtów, g — sïowo podwójne o rozmiarze o miu bajtów. Wprowadza to pewien zamÚt, poniewa czasami termin sïowo okre la równie warto ci 2-bajtowe. W takim przypadku podwójne sïowo lub DWORD oznacza war- to Ê 4-bajtowÈ. W ksiÈ ce tej terminy „sïowo” i DWORD bÚdÈ okre laïy warto ci 4-bajtowe. Do okre lania warto ci 2-bajtowych bÚdzie u ywany termin „póïsïowo”. Poni sze wyj cie z GDB obrazuje pamiÚÊ wy wietlanÈ w ró nych rozmiarach. (gdb) x/8xb $eip 0x8048384 <main+16>: 0xc7 0x45 0xfc 0x00 0x00 0x00 0x00 0x83 (gdb) x/8xh $eip 0x8048384 <main+16>: 0x45c7 0x00fc 0x0000 0x8300 0xfc7d 0x7e09 0xeb02 0xc713 (gdb) x/8xw $eip 0x8048384 <main+16>: 0x00fc45c7 0x83000000 0x7e09fc7d 0xc713eb02 0x8048394 <main+32>: 0x84842404 0x01e80804 0x8dffffff 0x00fffc45 (gdb) Je eli dobrze siÚ przyjrzysz, zauwa ysz w powy szych danych co dziwnego. Pierwsze polecenie examine pokazuje pierwsze osiem bajtów i, oczywi cie, polece- nia examine wykorzystujÈce wiÚksze jednostki wy wietlajÈ wiÚcej danych. Jednak e wynik pierwszego polecenia pokazuje, e pierwszymi dwoma bajtami sÈ 0xc7 i 0x45, ale gdy badane jest póïsïowo w dokïadnie tym samym adresie pamiÚci, pokazywana jest warto Ê 0x45c7, czyli bajty sÈ odwrócone. Ten sam efekt mo emy zauwa yÊ w przypadku peïnego 4-bajtowego sïowa wy wietlanego jako 0x00fc45c7. Je eli jednak pierwsze cztery bajty sÈ wy wietlane bajt po bajcie majÈ one kolejno Ê 0xc7, 0x45m 0xfc i 0x00. Jest tak, poniewa w procesorze x86 warto ci sÈ przechowywane w kolejno ci little endian, co oznacza, e najmniej istotny bajt jest przechowywany jako pierwszy. Je eli np. cztery bajty majÈ byÊ interpretowane jako jedna warto Ê, bajty muszÈ byÊ u yte w odwrotnej kolejno ci. Debuger GDB jest na tyle mÈdry, e wie, jak prze- chowywane sÈ warto ci, wiÚc gdy badane jest sïowo lub póïsïowo, bajty muszÈ byÊ odwrócone w celu wy wietlenia poprawnych warto ci w ukïadzie szesnastkowym. Przejrzenie tych wy wietlanych warto ci w systemie szesnastkowym i jako liczb dziesiÚtnych bez znaku mo e uïatwiÊ zrozumienie tej kwestii. (gdb) x/4xb $eip 0x8048384 <main+16>: 0xc7 0x45 0xfc 0x00 (gdb) x/4ub $eip 0x8048384 <main+16>: 199 69 252 0 (gdb) x/1xw $eip 44 0x200
  • 33. 0x8048384 <main+16>: 0x00fc45c7 (gdb) x/1uw $eip 0x8048384 <main+16>: 16532935 (gdb) quit The program is running. Exit anyway? (y or n) y reader@hacking:~/booksrc $ bc -ql 199*(256^3) + 69*(256^2) + 252*(256^1) + 0*(256^0) 3343252480 0*(256^3) + 252*(256^2) + 69*(256^1) + 199*(256^0) 16532935 quit reader@hacking:~/booksrc $ Pierwsze cztery bajty sÈ pokazane zarówno w notacji szesnastkowej, jak i standar- dowej, dziesiÚtnej. Kalkulator dziaïajÈcy w wierszu poleceñ bc posïu yï do wyka- zania, e je eli bajty zostanÈ zinterpretowane w nieprawidïowej kolejno ci, otrzy- mamy w wyniku zupeïnie nieprawidïowÈ warto Ê 3343252480. Kolejno Ê bajtów w danej architekturze jest istotnym czynnikiem, którego nale y byÊ wiadomym. ChoÊ wiÚkszo Ê narzÚdzi debugujÈcych i kompilatorów zajmuje siÚ automatycznie szczegóïami zwiÈzanymi z kolejno ciÈ bajtów, czasem bÚdziesz musiaï samodzielnie manipulowaÊ pamiÚciÈ. Oprócz konwersji kolejno ci bajtów, GDB mo e za pomocÈ polecenia examine wykonywaÊ inne konwersje. Widzieli my ju , e GDB mo e dezasemblowaÊ instruk- cje jÚzyka maszynowego na zrozumiaïe dla czïowieka instrukcje asemblera. Pole- cenie examine przyjmuje równie literÚ formatujÈcÈ i (skrót od instruction), co po- woduje wy wietlenie pamiÚci jako dezasemblowanych instrukcji jÚzyka asembler. reader@hacking:~/booksrc $ gdb -q ./a.out Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1". (gdb) break main Breakpoint 1 at 0x8048384: file firstprog.c, line 6. (gdb) run Starting program: /home/reader/booksrc/a.out Breakpoint 1, main () at firstprog.c:6 6 for(i=0; i < 10; i++) (gdb) i r $eip eip 0x8048384 0x8048384 <main+16> (gdb) x/i $eip 0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0 (gdb) x/3i $eip 0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0 0x804838b <main+23>: cmp DWORD PTR [ebp-4],0x9 0x804838f <main+27>: jle 0x8048393 <main+31> (gdb) x/7xb $eip 0x8048384 <main+16>: 0xc7 0x45 0xfc 0x00 0x00 0x00 0x00 (gdb) x/i $eip 0x8048384 <main+16>: mov DWORD PTR [ebp-4],0x0 (gdb) Programowanie 45
  • 34. W powy szym przykïadzie program a.out zostaï uruchomiony w GDB z punktem wstrzymania ustawionym w main(). Poniewa rejestr EIP wskazuje na pamiÚÊ, która faktycznie zawiera instrukcje w jÚzyku maszynowym, ïadnie poddajÈ siÚ one proce- sowi dezasemblacji. Wcze niejsza dezasemblacja za pomocÈ objectdump potwierdza, e siedem bajtów, które wskazuje EIP, to faktycznie jÚzyk maszynowy dla odpowiedniej instrukcji asemblera. 8048384: c7 45 fc 00 00 00 00 mov DWORD PTR [ebp-4],0x0 Ta instrukcja asemblera przenosi warto Ê 0 do pamiÚci znajdujÈcej siÚ pod ad- resem przechowywanym w rejestrze EBP minus 4. To wïa nie w tym miejscu pa- miÚci przechowywana jest zmienna i z jÚzyka C. Zmienna ta zostaïa zadeklarowana jako liczba caïkowita (int), wykorzystujÈca 4 bajty pamiÚci w przypadku procesora x86. To polecenie po prostu zeruje zmiennÈ i dla pÚtli for. Gdyby my teraz zbadali tÚ pamiÚÊ, zawieraïaby ona tylko przypadkowe mieci. PamiÚÊ w tej lokacji mo na zbadaÊ na ró ne sposoby: (gdb) i r ebp ebp 0xbffff808 0xbffff808 (gdb) x/4xb $ebp - 4 0xbffff804: 0xc0 0x83 0x04 0x08 (gdb) x/4xb 0xbffff804 0xbffff804: 0xc0 0x83 0x04 0x08 (gdb) print $ebp - 4 $1 = (void *) 0xbffff804 (gdb) x/4xb $1 0xbffff804: 0xc0 0x83 0x04 0x08 (gdb) x/xw $1 0xbffff804: 0x080483c0 (gdb) Rejestr EBP zawiera adres 0xbffff808, a instrukcja asemblera bÚdzie zapisywaïa do adresu o tej warto ci pomniejszonej o 4 — 0xbfffff804. Polecenie examine mo e zbadaÊ bezpo rednio ten adres pamiÚci lub wykonaÊ odpowiednie obliczenia w locie. Za pomocÈ polecenia print równie mo na wykonaÊ proste dziaïania arytmetyczne, a wynik zostanie zapisany w tymczasowej zmiennej w debugerze. Zmienna ta nosi nazwÚ $1 i mo e pó niej zostaÊ u yta do szybkiego uzyskania dostÚpu do okre lonego miejsca w pamiÚci. Ka da z przedstawionych wy ej metod pozwala uzyskaÊ ten sam rezultat: wy wietlenie znalezionych w pamiÚci 4 bajtów mieci, które zostanÈ wyzerowane po wykonaniu bie Ècej instrukcji. Uruchommy bie ÈcÈ instrukcjÚ, korzystajÈc z polecenia nexti, bÚdÈcego skrótem dla next instruction (nastÚpna instrukcja). Procesor odczyta instrukcjÚ z EIP, wykona jÈ i przestawi EIP na kolejnÈ instrukcjÚ. 46 0x200