 
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
IDZ DO
IDZ DO
KATALOG KSI¥¯EK
KATALOG KSI¥¯EK
TWÓJ KOSZYK
TWÓJ KOSZYK
CENNIK I INFORMACJE
CENNIK I INFORMACJE
CZYTELNIA
CZYTELNIA
Hack Wars. Tom 1.
Na tropie hakerów
Autor: John Chirillo
T³umaczenie: Pawe³ Koronkiewicz, Leonard Milcin
ISBN: 83-7197-599-6
Tytu³ orygina³u:
Format: B5, stron: 736
Zawiera CD-ROM
Hack Attacks Revealed: A Complete
Reference with Custom Security Hacking Toolkit
Ekspert w dziedzinie zabezpieczeñ, John Chirillo, zachêca Czytelnika do poznania
mrocznego i tajemniczego œwiata hakerów. Czerpi¹c z bogatego doœwiadczenia we
wspó³pracy z firmami Fortune 1000, Chirillo przedstawia ró¿ne sposoby wykorzystania
przez hakerów luk w zabezpieczeniach sieci oraz metody rozpoznawania tego rodzaju
zagro¿eñ. Uzupe³nieniem jest szczegó³owy opis pakietu TigerBox, umo¿liwiaj¹cego
hakerom przeprowadzanie skutecznych w³amañ, a administratorowi sieci — zyskanie
pewnoœci, ¿e jest w³aœciwie chroniona.
W tej prowokacyjnej ksi¹¿ce znajdziemy:
"
"
"
"
Opis protoko³ów sieciowych i technologii komunikacyjnych z punktu widzenia
hakera
Pe³ny opis stosowanych metod w³amañ, wyjaœniaj¹cy, jak dzia³aj¹ hakerzy,
crackerzy, "phreaks" i cyberpunki
Narzêdzia do gromadzenia informacji i skanowania sieci, umo¿liwiaj¹ce wykrycie
i przeanalizowanie przypadków naruszenia bezpieczeñstwa systemu
Dok³adne instrukcje, jak pos³ugiwaæ siê pakietem typu TigerBox
i wykorzystywaæ go do wykrywania ataków.
 
O Autorze .............................................................................................................9
Wstęp ................................................................................................................11
Rozdział 1. Protokoły komunikacyjne .................................................................15
Krótka historia Internetu ...................................................................................................15
IP — Internet Protocol ................................................................................................16
Datagramy IP — transportowanie, rozmiar i fragmentacja ........................................18
Adresy IP, klasy i maski podsieci ...............................................................................21
VLSM — krótka instrukcja tworzenia podsieci i odczytywania adresu IP ................22
ARP/RARP — rozpoznawanie adresu sprzętowego.........................................................31
ARP — transportowanie, budowa nagłówka pakietu .................................................31
RARP — transportowanie, dokonywanie transakcji ..................................................33
Usługa RARP..............................................................................................................33
TCP — Transmission Control Protocol ............................................................................33
Sekwencje oraz okna...................................................................................................34
Budowa nagłówka pakietu TCP..................................................................................35
Porty, końcówki, nawiązywanie połączenia ...............................................................37
UDP — User Datagram Protocol ......................................................................................37
Budowa i transportowanie datagramów UDP.............................................................38
Multiplexing, demultiplexing oraz porty UDP ...........................................................39
ICMP — Internet Control Message Protocol....................................................................39
Budowa i transportowanie pakietów ICMP ................................................................39
Komunikaty ICMP, wyszukiwanie maski podsieci ....................................................40
Przykłady datagramów ICMP.....................................................................................42
Rozdział 2. NetWare oraz NetBIOS .....................................................................43
NetWare — wprowadzenie ...............................................................................................43
IPX — Internetwork Packet Exchange .......................................................................44
SPX — Sequenced Packet Exchange .........................................................................48
Budowa i przykłady nagłówków SPX ........................................................................49
Zarządzanie połączeniami, przerywanie .....................................................................49
Algorytm Watchdog....................................................................................................50
Korekcja błędów, ochrona przed zatorami .................................................................51
NetBIOS — wprowadzenie...............................................................................................51
Konwencje nazywania, przykładowe nagłówki..........................................................51
Usługi NetBIOS ..........................................................................................................52
 
4
Hack Wars. Na tropie hakerów
NetBEUI — wprowadzenie ..............................................................................................53
Związki z NetBIOS.....................................................................................................54
Okna i liczniki.............................................................................................................54
Rozdział 3. Porty standardowe oraz związane z nimi usługi..................................55
Przegląd portów.................................................................................................................55
Porty TCP oraz UDP...................................................................................................56
Luki w bezpieczeństwie związane z portami standardowymi ....................................57
Niezidentyfikowane usługi................................................................................................69
Rozdział 4. Techniki rozpoznania i skanowania ...................................................99
Rozpoznanie ......................................................................................................................99
Katalog Whois ..........................................................................................................100
PING .........................................................................................................................102
Serwisy wyszukiwawcze ..........................................................................................105
Social Engineering ....................................................................................................106
Skanowanie portów .........................................................................................................107
Techniki skanowania portów ....................................................................................107
Popularne skanery portów.........................................................................................108
Przykładowy skan ...........................................................................................................120
Rozdział 5. Niezbędnik hakera..........................................................................127
Pojęcia związane z siecią ................................................................................................127
Model warstwowy — Open Systems Interconnection Model ..................................127
Rodzaje okablowania — przepustowość oraz maksymalna długość........................129
Konwersje pomiędzy postaciami dwójkowymi, dziesiątkowymi
i szesnastkowymi liczb .......................................................................................129
Funkcje wydajnościowe protokołów ........................................................................140
Technologie sieciowe ......................................................................................................141
Adresowanie MAC i kody producentów ..................................................................141
Ethernet .....................................................................................................................141
Token Ring................................................................................................................148
Sieci Token Ring i mostkowanie trasy nadawcy ......................................................149
Sieci Token Ring i translacyjne mostkowanie trasy nadawcy..................................153
Sieci FDDI ................................................................................................................155
Protokoły wybierania tras................................................................................................157
Protokoły wektorowo-odległościowe i protokoły stanów przyłączy........................157
Protokół RIP..............................................................................................................159
Protokół IGRP...........................................................................................................160
Protokół RTMP sieci Appletalk................................................................................161
Protokół OSPF ..........................................................................................................161
Ważne polecenia .............................................................................................................162
append .......................................................................................................................162
assign.........................................................................................................................164
attrib ..........................................................................................................................164
backup .......................................................................................................................165
break..........................................................................................................................166
chcp ...........................................................................................................................166
chdir (cd) ...................................................................................................................167
chkdsk .......................................................................................................................168
cls ..............................................................................................................................168
command...................................................................................................................168
comp..........................................................................................................................169
copy...........................................................................................................................170
ctty.............................................................................................................................171
 
Spis treści
5
date ............................................................................................................................171
del (erase)..................................................................................................................172
dir ..............................................................................................................................172
diskcomp ...................................................................................................................173
diskcopy ....................................................................................................................174
exe2bin ......................................................................................................................174
exit.............................................................................................................................175
fastopen .....................................................................................................................175
fc ...............................................................................................................................175
fdisk...........................................................................................................................177
find ............................................................................................................................177
format ........................................................................................................................178
graftabl ......................................................................................................................179
Graphics ....................................................................................................................179
join ............................................................................................................................180
keyb...........................................................................................................................181
label...........................................................................................................................182
mkdir (md) ................................................................................................................182
mode..........................................................................................................................183
more ..........................................................................................................................186
nlsfunc.......................................................................................................................186
path............................................................................................................................187
print ...........................................................................................................................187
prompt .......................................................................................................................188
recover.......................................................................................................................189
rename (ren) ..............................................................................................................190
replace .......................................................................................................................190
restore........................................................................................................................191
rmdir (rd)...................................................................................................................192
select .........................................................................................................................192
set ..............................................................................................................................193
share ..........................................................................................................................194
sort.............................................................................................................................194
subst ..........................................................................................................................195
sys .............................................................................................................................196
time ...........................................................................................................................196
tree.............................................................................................................................197
type............................................................................................................................197
ver .............................................................................................................................197
verify .........................................................................................................................198
vol .............................................................................................................................198
xcopy.........................................................................................................................198
Rozdział 6. Podstawy programowania dla hakerów ...........................................201
Język C ............................................................................................................................201
Wersje języka C ........................................................................................................202
Klasyfikowanie języka C ..........................................................................................203
Struktura języka C ...........................................................................................................203
Komentarze ...............................................................................................................205
Biblioteki...................................................................................................................205
Tworzenie programów ....................................................................................................205
Kompilacja ................................................................................................................205
Typy danych..............................................................................................................206
Operatory ..................................................................................................................210
 
6
Hack Wars. Na tropie hakerów
Funkcje......................................................................................................................212
Polecenia preprocesora C..........................................................................................216
Instrukcje sterujące ...................................................................................................219
Wejście-wyjście ........................................................................................................223
Wskaźniki .................................................................................................................226
Struktury ...................................................................................................................229
Operacje na plikach...................................................................................................234
Ciągi ..........................................................................................................................244
Obsługa tekstu...........................................................................................................250
Data i godzina ...........................................................................................................253
Pliki nagłówkowe......................................................................................................259
Debugowanie programu............................................................................................259
Błędy wartości zmiennoprzecinkowych ...................................................................260
Obsługa błędów ........................................................................................................260
Konwersja typów zmiennych....................................................................................263
Prototypy...................................................................................................................265
Wskaźniki do funkcji ................................................................................................266
Sizeof........................................................................................................................267
Przerwania.................................................................................................................267
Funkcja signal() ........................................................................................................270
Dynamiczne alokowanie pamięci .............................................................................271
Funkcja atexit() .........................................................................................................273
Wydajność.................................................................................................................274
Przeszukiwanie katalogów........................................................................................275
Dostęp do pamięci rozbudowanej .............................................................................278
Dostęp do pamięci rozszerzonej ...............................................................................282
Tworzenie programów TSR......................................................................................290
Rozdział 7. Metody przeprowadzania ataków ....................................................319
Streszczenie przypadku ...................................................................................................319
„Tylne wejścia” (backdoors) ...........................................................................................320
Zakładanie „tylnego wejścia” ...................................................................................322
Typowe techniki „tylnego wejścia” ................................................................................323
Filtry pakietów ..........................................................................................................323
Filtry stanowe............................................................................................................328
Bramy proxy i poziomu aplikacji .............................................................................333
Przeciążanie (flooding) ...................................................................................................333
Zacieranie śladów (log bashing) .....................................................................................342
Zacieranie śladów aktywności online .......................................................................343
Unikanie rejestrowania wciśnięć klawiszy ...............................................................344
Bomby pocztowe, spam i podrabianie korespondencji ...................................................355
Łamanie haseł (password cracking) ................................................................................357
Deszyfrowanie i krakowanie.....................................................................................357
Zdalne przejęcie kontroli.................................................................................................362
Krok 1. Rozpoznanie ................................................................................................363
Krok 2. Przyjazna wiadomość email ........................................................................363
Krok 3. Kolejna ofiara ..............................................................................................364
Monitorowanie komunikacji (sniffing) ...........................................................................366
Podrabianie IP i DNS (spoofing) ....................................................................................374
Studium przypadku ...................................................................................................375
Konie trojańskie ..............................................................................................................382
Infekcje wirusowe ...........................................................................................................388
Wardialing .......................................................................................................................391
„Złamanie” strony WWW (Web page hack)...................................................................392
 
Spis treści
7
Krok 1. Rozpoznanie ................................................................................................394
Krok 2. Uszczegółowienie danych ...........................................................................394
Krok 3. Rozpoczęcie właściwego ataku ...................................................................397
Krok 4. Poszerzenie wyłomu ....................................................................................397
Krok 5. „Hakowanie” strony.....................................................................................397
Rozdział 8. Bramy, routery oraz demony usług internetowych ............................401
Bramy i routery ...............................................................................................................401
3Com.........................................................................................................................402
Ascend/Lucent ..........................................................................................................409
Cabletron/Enterasys ..................................................................................................416
Cisco .........................................................................................................................423
Intel ...........................................................................................................................431
Nortel/Bay.................................................................................................................438
Demony serwerów internetowych...................................................................................442
Apache HTTP ...........................................................................................................443
Lotus Domino ...........................................................................................................445
Microsoft Internet Information Server......................................................................446
Netscape Enterprise Server .......................................................................................448
Novell Web Server....................................................................................................451
O’Reilly Web Site Professional ................................................................................454
Rozdział 9. Systemy operacyjne .......................................................................459
UNIX.........................................................................................................................460
AIX ...........................................................................................................................462
BSD...........................................................................................................................470
HP-UX ......................................................................................................................484
IRIX ..........................................................................................................................494
Linux .........................................................................................................................497
Macintosh..................................................................................................................522
Microsoft Windows ..................................................................................................527
Novell NetWare ........................................................................................................543
OS/2 ..........................................................................................................................552
SCO...........................................................................................................................566
Solaris .......................................................................................................................568
Rozdział 10. Serwery proxy i zapory firewall........................................................573
Bramy międzysieciowe ...................................................................................................573
BorderWare...............................................................................................................573
FireWall-1 .................................................................................................................577
Gauntlet.....................................................................................................................581
NetScreen ..................................................................................................................585
PIX ............................................................................................................................589
Raptor........................................................................................................................596
WinGate ....................................................................................................................599
Rozdział 11. TigerSuite — kompletny pakiet narzędzi do badania i ochrony sieci ...605
Terminologia ...................................................................................................................605
Wprowadzenie.................................................................................................................607
Instalacja ...................................................................................................................610
Moduły ............................................................................................................................613
Moduły grupy System Status ....................................................................................614
TigerBox Tookit..............................................................................................................619
TigerBox Tools .........................................................................................................619
TigerBox Scanners....................................................................................................624
 
8
Hack Wars. Na tropie hakerów
TigerBox Penetrators ................................................................................................626
TigerBox Simulators .................................................................................................627
Przykładowy scenariusz włamania..................................................................................628
Krok 1. Badanie celu.................................................................................................629
Krok 2. Rozpoznanie ................................................................................................631
Krok 3. Socjotechnika...............................................................................................633
Krok 4. Atak..............................................................................................................635
Podsumowanie ................................................................................................................635
Dodatek A Klasy adresów IP oraz podział na podsieci.......................................637
Dodatek B Porty standardowe .........................................................................641
Dodatek C Pełna lista portów specjalnych .......................................................645
Dodatek D Porty usług niepożądanych .............................................................685
Dodatek E Zawartość płyty CD .......................................................................691
Skorowidz .........................................................................................................701
 
Rozdział 6.
Język C
Dla  każdego  hakera,  młodego  czy  starego,  mniej  lub  bardziej  doświadczonego,  zna-
jomość  języka  C  jest  jednym  z  fundamentów  wiedzy.  Niemal  wszystkie  narzędzia
i programy, stosowane w trakcie analiz sieci i włamań, powstają właśnie w tym języ-
ku.  Również  w  niniejszej  książce  większość  przedstawianego  kodu  to  właśnie  kod
źródłowy w języku C. Programy te można modyfikować, dostosowywać do własnych
potrzeb i odpowiednio kompilować.
W  pracy  nad  niniejszym  rozdziałem  wykorzystano  obszerne  fragmenty  pracy  guru
programowania Matthew Proberta. Mają one pełnić funkcję wprowadzenia do pro-
gramowania w języku C i umożliwić stosowanie przedstawianych w książce (i załą-
czonych  na  CD-ROM-ie)  listingów  programów.  Pełny  kurs  języka  znajdziesz  w  nie-
jednej książce wydawnictwa Helion.
Język C wyróżniają następujące cechy, które omawiamy niżej.
J
J
J
J
Blokowe konstrukcje sterowania wykonywaniem programu (typowe dla
większości języków wysokiego poziomu).
J
J
J
J
Swobodne operowanie podstawowymi obiektami „maszynowymi” (takimi jak
bajty) i możliwość odwoływania się do nich przy użyciu dowolnej, wymaganej
w danej sytuacji, perspektywy obiektowej (typowe dla języków asemblerowych).
J
J
J
J
Możliwość wykonywania operacji zarówno wysokiego poziomu (na przykład
arytmetyka zmiennoprzecinkowa), jak i niskiego poziomu (zbliżonych
do instrukcji języka maszynowego), co umożliwia tworzenie kodu wysoce
zoptymalizowanego bez utraty jego przenośności.
 
202
Hack Wars. Na tropie hakerów
Przedstawiony  w  niniejszym  rozdziale  opis  języka  C  bazować  będzie  na  funkcjach
oferowanych  przez  większość  kompilatorów  dla  komputerów  PC.  Powinien  dzięki
temu  umożliwić  rozpoczęcie  tworzenia  prostych  programów  osobom  nieposiadają-
cym szerokiej wiedzy o języku (uwzględnimy między innymi funkcje zapisane w pa-
mięci ROM i funkcje DOS-u).
Przyjmujemy  założenie,  że  masz,  drogi  Czytelniku,  dostęp  do  kompilatora  C  i  od-
powiedniej  dokumentacji  funkcji  bibliotecznych.  Programy  przykładowe  powstały
w Turbo C firmy Borland; większość elementów niestandardowych tego narzędzia
uwzględniono również w późniejszych edycjach Microsoft C.
Wersje języka C
W  pierwotnej  edycji  języka  C  (jeszcze  przed  publikacją  Kernighana  i  Ritchie’ego,
The C Programming Language, Prentice-Hall 1988 (polskie wydanie: Język ANSI C,
Wydawnictwa  Naukowo-Techniczne  1994))  zintegrowane  operatory  przypisania  (+=,
*= itd.) definiowane były odwrotnie (tj. =+, =* itd.). Znakomicie utrudniało to inter-
pretację wyrażeń takich jak:
co mogłoby znaczyć
lub
Ritchie szybko zauważył dwuznaczność takiego zapisu i zmodyfikował go do postaci
znanej dzisiaj (+=, *= itd.). Mimo to wciąż stosowanych jest wiele odmian będących
rodzajem wypośrodkowania między pierwotną wersją języka C Kernighana i Ritchie’ego
a językiem ANSI C. Różnice między nimi dotyczą przede wszystkim:
J
J
J
J
wprowadzenia prototypów funkcji i zmiany preambuły definicji funkcji,
aby dostosować ją do stylu prototypów,
J
J
J
J
wprowadzenia znaku wielokropka (...) do oznaczenia list argumentów o zmiennej
długości,
J
J
J
J
wprowadzenia słowa kluczowego
(dla funkcji, które nie zwracają wartości)
i typu
dla ogólnych zmiennych wskaźnikowych,
J
J
J
J
wprowadzenie w preprocesorze mechanizmów scalania ciągów, wklejania
elementu (token-pasting) i zamiany na ciąg (string-izing),
J
J
J
J
dodanie w preprocesorze translacji „trygrafów” (trigraph) — trójznakowych
sekwencji reprezentujących znaki specjalne,
J
J
J
J
dodanie w preprocesorze dyrektywy
i formalizacja pseudofunkcji
,
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
203
J
J
J
J
wprowadzenie ciągów i znaków wielobajtowych, zapewniających obsługę
języków narodowych,
J
J
J
J
wprowadzenie słowa kluczowego
(jako uzupełnienie słowa
,
stosowane w deklaracjach liczb całkowitych) i jednoargumentowego
operatora plus (
).
Klasyfikowanie języka C
Szerokie możliwości języka C, dopuszczenie bezpośredniego operowania na adresach
i danych w pamięci oraz strukturalne podejście do programowania sprawiają, że język
ten klasyfikuje się jako „język programowania średniego poziomu”. Znajduje to wyraz
w mniejszej liczbie gotowych rozwiązań niż w językach wysokiego poziomu, takich
jak BASIC, ale wyższym poziomie strukturalnym niż niskopoziomowy Assembler.
Słowa kluczowe
Pierwotna  edycja  języka  C  definiuje  27  słów  kluczowych.  Komitet  ANSI  dodał  do
nich 5 nowych. Wynikiem są dwa standardy języka, choć norma ANSI przejęła więk-
szość elementów od Kerninghana i Ritchie’ego. Oto lista:
Warto zwrócić uwagę, że niektóre kompilatory C wprowadzają dodatkowe słowa klu-
czowe, specyficzne dla środowiska sprzętowego. Warto zapoznać się z nimi.
Struktura języka C
Język  C  wymaga  programowania  strukturalnego.  Oznacza  to,  że  na  program  składa
się pewna grupa nawzajem wywołujących się bloków kodu. Dostępne są różnorodne
polecenia służące do konstruowania pętli i sprawdzania warunków:
Blok programu w języku C ujmowany jest w nawiasy klamrowe (
). Może on być
kompletną  procedurą,  nazywaną  funkcją  lub  częścią  kodu  funkcji.  Przyjrzyjmy  się
przykładowi:
 
204
Hack Wars. Na tropie hakerów
!
"
#
!#
$
Instrukcje  wewnątrz  nawiasów  klamrowych  wykonane  zostaną  tylko  wtedy,  gdy  speł-
niony zostanie warunek 
.
Jako kolejny przykład przedstawimy pełny blok kodu funkcji, zawierający wewnątrz
blok pętli:
%&'()
"
#
"
*+, ! !*#
*-*.#
$
!//0 !#
#
$
Zwróćmy uwagę, że każdy wiersz instrukcji zakończony jest średnikiem, o ile nie jest
sygnałem  początku  bloku  kodu  (w  takim  przypadku  kolejnym  znakiem  jest  nawias
klamrowy). Język C rozpoznaje wielkość liter, ale nie bierze pod uwagę białych zna-
ków.  Odstępy  między  poleceniami  są  pomijane,  stąd  konieczność  użycia  średnika,
aby oznaczyć koniec wiersza. Tego rodzaju podejście powoduje, że następujące pole-
cenia interpretowane są jako identyczne:
!#
!#
!#
Ogólna postać programu w języku C jest następująca:
J
J
J
J
instrukcje preprocesora kompilacji,
J
J
J
J
globalne deklaracje danych.
J
J
J
J
deklaracje i definicje funkcji (włączając w to zawartość programu):
"
$
"
$
1
"
$
2
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
205
"
$
Komentarze
Podobnie jak większość języków, C pozwala umieszczać w kodzie programu komen-
tarze. Ich ogranicznikami są symbole 
i
:
34'5 56 743
(Równie  często  korzysta  się  z  komentarzy  jednoliniowych,  otrzymywanych  poprzez
sekwencję //, np.:
33' 85 92:2
Biblioteki
Programy  w  języku  C  kompiluje  się  i  łączy  z  funkcjami  bibliotecznymi,  dostarcza-
nymi  wraz  z  kompilatorem.  Na  biblioteki  składają  się  funkcje  standardowe,  których
działanie  zdefiniowane  zostało  w  normie  ANSI.  Ich  powiązanie  z  konkretnym  kom-
pilatorem zapewnia dostosowanie do platformy sprzętowej. Wynika stąd, że standardowa
funkcja  biblioteczna 
działa tak samo w systemach DEC VAX i IBM PC,
choć różni się jej, zapisany w bibliotece, kod maszynowy. Programista C nie musi za-
głębiać się w zawartość bibliotek, wymagana jest jedynie umiejętność ich stosowania
i znajomość działania funkcji, które pozostają niezmienne na każdym komputerze.
Tworzenie programów
Kompilacja
Zanim zajmiemy się funkcjami, poleceniami, sekwencjami i innymi zaawansowanymi
zagadnieniami, przyjrzyjmy się praktycznemu przykładowi, w którym doprowadzimy
do  skompilowania  kodu.  Kompilowanie  programów  C  jest  stosunkowo  prostą  czyn-
nością, jednak różni się zależnie od stosowanego kompilatora. Kompilatory wyposażone
w  menu  umożliwią  skompilowanie,  skonsolidowanie  i  uruchomienie  programu  jed-
nym  wciśnięciem  klawisza.  Podchodząc  jednak  do  zagadnienia  możliwie  uniwersal-
nie i tradycyjnie, przeprowadzimy poniżej całą procedurę w oparciu o wiersz poleceń.
W dowolnym edytorze wprowadzamy poniższy fragment kodu i zapisujemy plik jako
przyklad.c:
34
;
43
 
206
Hack Wars. Na tropie hakerów
< 20
"
*=>+*#
$
Kolejnym  krokiem  jest  skompilowanie  kodu  do  postaci  pliku  programu  —  dopiero
wtedy można będzie go uruchomić (czy też wykonać). W wierszu poleceń w tym sa-
mym katalogu, w którym zapisaliśmy plik przyklad.c, wprowadzamy następujące po-
lecenie kompilacji:
2
Nie wolno zapominać, że składnia polecenia kompilacji zależy od kompilatora. Nasz
przykład opiera się na standardzie języka C. Współcześnie jednak popularne jest sto-
sowanie składni wywodzącej się z kompilatora GNU C:
2
Po  wykonaniu  takiego  polecenia  nasz  kod  jest  już  skompilowany  i  ma  postać  pliku
programu,  który  możemy  uruchomić.  Wynik  jego  działania  łatwo  wydedukować
z prostego kodu:
=>
9
To wszystko! Kompilowanie małych programów w C nie jest trudne, należy jedynie
mieć  świadomość  szkodliwych  niekiedy  efektów  ich  działania.  Programy  przedsta-
wiane na stronach tej książki i załączone na CD-ROM-ie są oczywiście znacznie bar-
dziej skomplikowane, jednak zasady pozostają te same.
Typy danych
W  języku  C  wyróżnia  się  cztery  podstawowe  typy  danych:  znakowy,  całkowity,
zmiennoprzecinkowy  i  nieokreślony.  Odpowiadają  im  słowa  kluczowe: 
,
,
i
. Dalsze typy danych tworzy się na tej podstawie, dodając modyfikatory:
(ze znakiem),
(bez znaku),
(długa) i
(krótka). Modyfika-
tor
jest elementem domyślnym, co sprawia, że jego użycie może się okazać
konieczne  jedynie  w  wypadku  gdy  zastosowano  przełącznik  kompilacji  nakazujący
domyślne korzystanie ze zmiennych bez znaku. Rozmiar każdego typu danych zależy
od  platformy  sprzętowej,  jednak  norma  ANSI  wyznacza  pewne  zakresy  minimalne,
zestawione w tabeli 6.1.
W praktyce tak określone konwencje oznaczają, że typ danych
nadaje się najle-
piej  do  przechowywania  zmiennych  typu  znacznikowego,  takich  jako  kody  stanu,
o ograniczonym zakresie wartości. Można również korzystać z typu 
. Gdy jednak
zakres wartości nie przekracza 127 (lub 255 dla
), każda deklarowana
w ten sposób zmienna przyczynia się do niepotrzebnego obciążania pamięci.
Natomiast trudniejsze jest pytanie o to, z którego typu liczb rzeczywistych korzystać
— 
,
czy
. Gdy wymagana jest dokładność, na przykład
w aplikacji stosowanej w księgowości, instynktownie powinniśmy użyć typu
,
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
207
Tabela 6.1.
Rozmiary i zakresy typów danych języka C
Typ
Rozmiar
Zakres
8
–128 do 127
8
0 do 255
16
–32 768 do 32 767
16
0 do 65 535
32
–2 147 483 648 do 2 147 483 647
32
0 do 4 294 967 295
32
precyzja 6-cyfrowa
64
precyzja 10-cyfrowa
80
precyzja 10-cyfrowa
wiąże się to jednak z wykorzystaniem przez każdą zmienną 10 bajtów. Obliczenia na
liczbach  rzeczywistych  nie  są  tak  dokładne  jak  na  liczbach  całkowitych,  warto  więc
zawsze  rozważyć  użycie  typu 
i „obejście” problemu. Typ danych
nie jest
zbyt dobry, gdyż jego 6-cyfrowa precyzja nie zapewnia dokładności, na której zawsze
będziemy  mogli  polegać.  Ogólną  zasadą  jest  korzystanie  z  typów  całkowitych  tak
szeroko,  jak  tylko  jest  to  możliwe,  a  gdy  pojawia  się  konieczność  użycia  liczb  rze-
czywistych, wprowadzenie typu 
.
Deklarowanie zmiennej
Każda zmienna musi zostać zadeklarowana przed użyciem. Ogólną postacią deklara-
cji zmiennej jest:
#
Aby więc przykładowo zadeklarować zmienną
typu
, przeznaczoną do przecho-
wywania wartości z zakresu od –32 768 do 32 767, użyjemy instrukcji:
#
Ciągi znakowe deklarować można jako tabele znaków:
? @#
Deklaracja ciągu o nazwie
!"#
i długości 30 znaków, wyglądać będzie następująco:
?A!@#
Tablice  danych  innych  typów  mogą  mieć  więcej  niż  jeden  wymiar.  Oto  deklaracja
dwuwymiarowej tablicy liczb całkowitych:
? !@? !@#
Elementy tablicy wywołujemy jako:
?!@?!@
?!@? @
?@?@
 
208
Hack Wars. Na tropie hakerów
Wyróżnia  się  trzy  poziomy  dostępu  do  zmiennych:  lokalny,  na  poziomie  modułu
i globalny.  Zmienna  deklarowana  wewnątrz  bloku  kodu  będzie  dostępna  wyłącznie
dla instrukcji wewnątrz tego bloku. Zmienna deklarowana poza blokami kodu funkcji,
ale poprzedzona modyfikatorem 
, będzie dostępna wyłącznie instrukcjom we-
wnątrz  modułu  kodu  źródłowego.  Zmienna  deklarowana  poza  blokami  kodu  funkcji
i niepoprzedzona modyfikatorem będzie dostępna dla dowolnych instrukcji w dowol-
nym module programu. Na przykład:
#
#
7 5; 5 B5
5 B 6 8 B
5 55C5 5 2D CE8 6
; 5692:2
"
#
#
$
5
"
34F5 G!43
!
"
#
!# 1!# HH
*+=,*#
$
$
W powyższym przykładzie zmienna
jest dostępna dla wszystkich, kompilowa-
nych jako jeden program, modułów kodu źródłowego. Zmienna
jest osiągalna dla
wszystkich instrukcji w funkcjach
i
#$
, ale pozostaje niewidoczna
z poziomu innych modułów. Zmienne
i
%
są dostępne wyłącznie instrukcjom we-
wnątrz funkcji
. Z kolei zmienna
może być użyta wyłącznie przez instrukcje
wewnątrz bloku kodu po instrukcji
.
Jeżeli drugi blok kodu faktycznie ma skorzystać ze zmiennej
, wymagane będzie
umieszczenie w nim deklaracji zmiennej globalnej
:
#
5
"
$
Język C nie stawia szczególnych przeszkód w przypisywaniu do siebie różnych typów
danych. Przykładowo możemy zadeklarować zmienną typu 
, co spowoduje przy-
pisanie  do  przechowywania  jej  wartości  jednego  bajtu  danych.  Można  podjąć  próbę
przypisania do niej wartości spoza tego zakresu:
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
209
"
I!!!#
$
Zmienna
może przechowywać wartości z zakresu od –127 do 128, a więc wartość 5000
nie zostanie przypisana.
przyjmie jednak wartość 136.
Potrzeba  przypisania  różnych  typów  danych  nie  jest  niczym  oryginalnym.  Aby  po-
wstrzymać kompilator od generowania ostrzeżeń o takich operacjach, można skorzy-
stać z instrukcji konwersji (cast statement), informując kompilator o tym, że operacja
wykonywana jest świadomie. Instrukcję taką budujemy, umieszczając przed zmienną
lub wyrażeniem nazwę typu danych ujętą w nawiasy:
"
#
#
!!31I#
#
$
Operacja rzutowania
informuje kompilator o konieczności konwersji wartości
zmiennej zmiennoprzecinkowej
do liczby całkowitej, zanim ta zostanie przypisana
do zmiennej
%
.
Parametry formalne
Funkcja  w  języku  C  może  przyjmować  parametry  przekazywane  przez  funkcję  wy-
wołującą.  Parametry  te  deklaruje  się  podobnie  jak  zmienne,  podając  ich  nazwy  we-
wnątrz towarzyszących nazwie funkcji nawiasów:
JKLM
"
34MGE 8 43
4#
$
"
#
#
#
I#
N#
JKLM #
*--G6-+* #
$
 
210
Hack Wars. Na tropie hakerów
Modyfikatory dostpu
Stosuje się dwa modyfikatory dostępu:
i
. Wartość zmiennej zadekla-
rowanej jako
nie może zostać zmieniona przez program, wartość zmiennej za-
deklarowanej jako
może zostać zmieniona przez program. Dodatkowo, za-
deklarowanie zmiennej jako
uniemożliwia kompilatorowi zaalokowanie jej
do rejestru i ogranicza przeprowadzaną na niej optymalizację.
Typy klas przechowywania zmiennych
Język C przewiduje cztery rodzaje przechowywania zmiennych:
,
,
i
. Typ
umożliwia modułowi kodu źródłowego dostęp do zmiennej
zadeklarowanej w innym module. Zmienne
dostępne są wyłącznie z poziomu
bloku kodu, w którym zostały zadeklarowane. Dodatkowo, jeżeli zmienna ma zasięg
lokalny, zachowuje swoją wartość między kolejnymi wywołaniami bloku kodu.
Zmienne rejestrowe (
) są, gdy tylko jest to możliwe, przechowywane w reje-
strach procesora. Zapewnia to najszybszy dostęp do ich wartości. Typ
stosuje się
wyłącznie w odniesieniu do zmiennych lokalnych.  Nakazuje  on  zachowywanie  war-
tości zmiennej lokalnej. Ponieważ jest to modyfikator domyślny, rzadko można spo-
tkać go w programach.
Operatory
Operatory to elementy kodu, które nakazują wykonanie obliczeń na zmiennych. W ję-
zyku C dostępne są następujące:
.
adres,
4
pośredniość,
H
plus jednoargumentowy,
minus jednoargumentowy,
O
dopełnienie bitowe,
>
negacja logiczna,
HH
jako prefiks — preinkrementacja, jako sufiks — postinkrementacja,
PP
jako prefiks — predekrementacja, jako sufiks — postdekrementacja,
H
dodawanie,
odejmowanie,
4
mnożenie,
3
dzielenie,
-
reszta z dzielenia (modulo),
przesunięcie w lewo,
00
przesunięcie w prawo,
.
bitowa operacja AND,
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
211
/
bitowa operacja OR,
Q
bitowa operacja XOR,
..
logiczna operacja AND,
//
logiczna operacja OR,
przypisanie,
4
przypisanie iloczynu,
3
przypisanie ilorazu,
-
przypisanie reszty (modułu),
H
przypisanie sumy,
przypisanie różnicy,
przypisanie przesunięcia w lewo,
00
przypisanie przesunięcia w prawo,
.
przypisanie wyniku bitowej operacji AND,
/
przypisanie wyniku bitowej operacji OR,
Q
przypisanie wyniku bitowej operacji XOR,
mniejsze niż,
0
większe niż,
mniejsze lub równe,
0
większe lub równe,
równe,
>
różne od,
2
bezpośredni selektor składnika,
0
pośredni selektor składnika,
RS
jeżeli
to prawda, to , w przeciwnym razie %&
?@
definiowanie tablic,
nawiasy oddzielają warunki i wyrażenia,
222
wielokropek wykorzystuje się w listach parametrów formalnych prototypów
funkcji do deklarowania zmiennej liczby parametrów lub parametrów
zmiennych typów.
Aby  zilustrować  sposób  korzystania  z  podstawowych  operatorów,  przyjrzyjmy  się
krótkiemu programowi:
"
#
#
#
I#3495 BI43
31#3495 B5143
41#3495 B 85143
34F CC BE543
 
212
Hack Wars. Na tropie hakerów
*M5 *#
*M5 *#
$
Typowym sposobem zwiększenia wartości zmiennej o 1 jest wiersz:
H
Język C dostarcza operatora inkrementacji, wystarczy więc napisać:
HH
W podobny sposób korzystamy z operatora dekrementacji, czyli zmniejszania war-
tości o 1:
Pozostałe  operatory  matematyczne  wykorzystujemy  podobnie.  Warto  jednak  pamię-
tać o wprowadzanych przez język C możliwościach zapisu skróconego:
Zapis typowy
Zapis w j+zyku C
H HH
 
41
41
3
3
-I
-I
Funkcje
Funkcje to procedury kodu źródłowego tworzące program w języku C. Ich ogólną po-
stacią jest:
"
$
to typ zwracanej przez funkcję wartości:
,
,
,
itp.
Kod wewnątrz funkcji C pozostaje niewidoczny dla innych funkcji C. Nie można wy-
konywać  skoków  z  jednej  funkcji  do  wnętrza  innej.  Funkcje  mogą  jedynie  wywoły-
wać  inne  funkcje.  Nie  wolno  również  definiować  funkcji  wewnątrz  innych  funkcji.
Definicja musi zostać umieszczona bezpośrednio na poziomie modułu kodu.
Parametry przekazywane są do funkcji jako wartości lub jako odwołania (wskaźniki).
Gdy parametr jest przekazywany jako wartość, funkcja otrzymuje kopię tej wartości.
Parametr przekazywany jako odwołanie jest jedynie wskaźnikiem do właściwego pa-
rametru. Pozwala to na zmianę jego wartości z poziomu wywołanej funkcji. W poniż-
szym przykładzie przekazujemy dwa parametry jako wartość  do  funkcji 
#$
,
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
213
która następnie podejmuje próbę zmiany wartości przekazanych zmiennych. Drugim
krokiem jest przekazanie tych samych parametrów do funkcji 
#$
, która rów-
nież podejmuje próbę zmiany wartości zmiennych:
< 20
5
"
34T 55 5 5 B43
41#
41#
*+, BE 5-2, BE 5-*#
#
$
5 4 4
"
34T 55 5 5;43
4441#
4441#
*+, BE 5 -2, BE 5 -*44#
4#
$
"
#
#
#
I#
N#
5#
5 ..#
*+, BE- BE- BE-*#
$
#$
nie zmienia wartości otrzymanych parametrów. Modyfikowana jest za-
wartość wskazywanych parametrami adresów pamięci. O ile
#$
otrzymuje
z funkcji
wartości zmiennych
i
%
,
#$
otrzymuje z funkcji
ich
adresy w pamięci.
Przekazywanie tablicy do funkcji
Następujący  program  przekazuje  do  funkcji  tablicę,  a  funkcja  nadaje  wartości  ele-
mentom tablicy:
 
214
Hack Wars. Na tropie hakerów
< 20
5 ?@
"
#
!# !!#HH
?@#
$
"
? !!@#
#
5 #
!# !!#HH
*+, BE --* ?@#
$
Parametr funkcji,
'(
, jest tablicą dowolnej długości. Deklaracja taka jest możli-
wa, ponieważ kompilator przekazuje jedynie adres początkowy tablicy, a nie wartości
poszczególnych  jej  elementów.  Konsekwencją  tego  jest  fakt,  że  funkcja  może  zmie-
niać wartości elementów tablicy. Aby uniemożliwić funkcji wprowadzanie modyfika-
cji, konieczne jest użycie typu 
:
5 ?@
"
$
Przy takiej deklaracji wiersz zmieniający zawartość tablicy wywołałby błąd kompila-
cji. Określenie parametru jako wartości stałej nie likwiduje jednak pośredniości jego
przekazania. Ilustruje to poniższy program:
< 20
5 ?@
"
4 #
#
34' 5 8U U43
34 5V43
345 V 43
#
!# !!#HH
"
4 #
HH#
$
$
"
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
215
? !!@#
#
5 #
!# !!#HH
*+, BE --* ?@#
$
Przekazywanie parametrów funkcji main()
Język C umożliwia przekazanie parametrów do uruchamianego programu z poziomu
systemu operacyjnego. Do ich odczytania wykorzystuje się zmienne 
i
'(
:
< 20
4?@
"
#
!##HH
*+, - -*?@#
$
Parametr
przechowuje liczbę przekazanych programowi parametrów. W tablicy
'(
zapisane są ich adresy;
'(
jest zawsze nazwą uruchamianego programu.
Mechanizm ten ma szczególne znaczenie dla aplikacji wymagających dostępu do pli-
ków systemowych i danych. Rozważmy następującą sytuację: mała aplikacja obsługi
baz danych przechowuje swoje dane w pojedynczym pliku dane.dat; aplikacja ta musi
zostać tak zaprojektowana, aby można było uruchomić ją z dowolnego katalogu, czy
to na dysku twardym, czy dyskietce; musi również zapewnić uruchamianie za pośred-
nictwem ścieżki wyszukiwania DOS-u (
). Do poprawnej pracy aplikacji jest więc
wymagane,  aby  zawsze  mogła  odnaleźć  plik  dane.dat.  Rozwiązanie  takie  zapewni
przyjęcie założenia, że plik danych jest zawsze w identycznym katalogu co sam pro-
gram. Poniższy fragment ilustruje wykorzystanie parametrów 
i
w celu utwo-
rzenia ścieżki do pliku danych aplikacji:
< 20
( ? W!@#
4?@
"
4(*XD'D2XD'*#
4#
( ?!@#
( *2*# ;
å 92:2
KYZZ
"
349 5 27LJ43
 
216
Hack Wars. Na tropie hakerów
( *2*#
$
34, 5 B43
4 >U++U
#
(#
$
Przedstawiony program tworzy i zapisuje w zmiennej
!" )#
ciąg postaci ścież-
ka\dane.dat. Jeżeli więc przykładową nazwą pliku uruchomieniowego będzie test.exe
i  zostanie  on  umieszczony  w  katalogu  \borlandc,  zmiennej 
!" )#
przypisany
zostanie ciąg
* * +
.
Wyj#cie z funkcji
Polecenie
powoduje natychmiastowe wyjście z funkcji. Jeżeli w deklaracji
funkcji podano typ zwracanej wartości, w poleceniu
należy użyć parametru te-
go samego typu.
Prototypy funkcji
Prototypy funkcji umożliwiają kompilatorowi C sprawdzanie poprawności przekazy-
wanych,  do  i  z  funkcji,  danych.  Ma  to  istotne  znaczenie  jako  zabezpieczenie  przed
przekroczeniem zakresu zaalokowanego dla zmiennej obszaru pamięci. Prototyp funkcji
umieszcza się na początku programu po poleceniach preprocesora (takich jak 
)
i przed deklaracjami funkcji.
Polecenia preprocesora C
W języku C w treści kodu źródłowego można umieszczać polecenia dla kompilatora.
Określa się je terminem polecenia preprocesora. Norma ANSI definiuje następujące:
<
<
<
<
<
<
<
<
<
<
<
<
Wszystkie  polecenia  preprocesora  rozpoczyna  znak  krzyżyka  (hash),  czyli  #.  Każde
wymaga osobnego wiersza kodu (uzupełnionego ewentualnie komentarzem). Poniżej
przedstawiamy krótkie omówienie.
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
217
#define
Polecenie
tworzy identyfikator, który kompilator zastąpi podanym ciągiem
w danym module kodu źródłowego. Na przykład:
<TDZF&!
<'[Y&>TDZF&
Kompilator zastąpi wszystkie dalsze wystąpienia ciągu
,-./0
znakiem
, a wszystkie
dalsze wystąpienia ciągu
1230
— ciągiem
4
. Zastępowaniu nie podlegają identyfi-
katory wewnątrz znaków cudzysłowu, a więc wiersz:
*'[Y&*#
nie zostanie zmieniony, ale
*-*TDZF&#
podlega modyfikacji.
Polecenie
może również zostać użyte do definiowania makr, także makr z pa-
rametrami. Do zapewnienia poprawności zastąpień zaleca się ujmowanie parametrów
w nawiasy. W poniższym przykładzie deklarujemy makro o nazwie 
, przyj-
mujące dwa parametry i zwracające ten z nich, którego wartość jest większa.
< 20
< 0 RS
"
*+-5 6*IN#
$
#error
Polecenie
powoduje przerwanie procesu kompilacji i wyświetlenie podanego
tekstu, na przykład:
<F\LJ9]ZL,DK&XLJLXYZY:
powoduje zatrzymanie kompilacji i wyświetlenie:
F\LJ9]ZL,DK&XLJLXYZY:
#include
Polecenie
nakazuje kompilatorowi odczytanie i przetworzenie zawartości
dodatkowego  pliku  źródłowego.  Nazwa  pliku  musi  zostać  ujęta  w  cudzysłów  lub
wstawiona między znaki 
5
, na przykład:
< * 12*
< 20
Jeżeli nazwa pliku została wpisana między znaki
5
, kompilator wyszukuje go w kata-
logu określonym w konfiguracji. Jest to zasada ogólna.
 
218
Hack Wars. Na tropie hakerów
#if, #else, #elif, #endif
Grupa poleceń
dostarcza mechanizmu kompilacji warunkowej. Stosowana jest
dość typowa składnia:
<
<
<
Polecenie
to skrócona postać
:
<
<
<
#ifdef, #ifndef
Rozwinięciem tych poleceń jest
(jeżeli zdefiniowano) i
(jeżeli nie zdefiniowano). Konstrukcje składniowe są następujące:
<
<
<
<
<
<
to identyfikator utworzony za pomocą deklaracji
.
#undef
Polecenie
usuwa definicję makra utworzonego przy użyciu wcześniejszej in-
strukcji
.
#line
Polecenie
modyfikuje zmienne globalne kompilatora
)).670))
i
)),6.0))
.
Ogólną postacią instrukcji jest:
< * *
Wartość
zostaje umieszczona w zmiennej
)).670))
, a
8 8
— w zmien-
nej
)),6.0))
.
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
219
#pragma
Umożliwia korzystanie z poleceń specyficznych dla kompilatora.
Instrukcje steruj"ce
Jak  w  każdym  języku  programowania,  również  w  C,  znajdziemy  instrukcje  spraw-
dzające wartość wyrażenia. Wynikiem takiego sprawdzenia jest wartość 
1230
lub
,-./0
.
Wartości
,-./0
odpowiada liczba
, a
1230
— liczba różna od zera.
Instrukcje wykonania warunkowego
Podstawową instrukcją wykonania warunkowego jest
o następującej składni:
gdzie
może być instrukcją pojedynczą lub ujętym w nawiasy klamrowe
blokiem kodu. Element
jest opcjonalny. Jeżeli wartością
jest
1230
,
wykonywana jest instrukcja podana bezpośrednio po nim. W pozostałych przypadkach
wykonywana jest instrukcja podana po słowie 
(o ile ta część składni została użyta).
Alternatywą dla konstrukcji
+++
jest polecenie
9:
w postaci:
Jeżeli wartością wyrażenia jest
1230
, wykonywana jest pierwsza instrukcja. W pozo-
stałych przypadkach wykonywana jest instrukcja druga. Ilustruje to przykład:
< 20
"
#
W#
*+ -*-1!R* *S* *#
$
Język C oferuje również instrukcję
"
, ułatwiającą porównywanie wyrażenia
z pewną listą wartości. Wykonywane są instrukcje powiązane z pierwszą dopasowaną
wartością listy. Składnia polecenia 
"
jest następująca:
"
S
#
!S
#
2
2
 
220
Hack Wars. Na tropie hakerów
S
#
S
$
Użycie instrukcji
#
nie jest wymagane, ale jej pominięcie powoduje dalsze po-
równywanie wyrażenia z kolejnymi elementami listy wartości.
< 20
"
#
W#
"
!S *+G6*#
#
S *+G65*#
#
1S *+G6*#
#
AS *+G6 *#
#
S *+5 6 *#
$
$
Instrukcje
"
można zagnieżdżać.
Instrukcje iteracji
W języku C stosuje się trzy instrukcje pętli (iteracji):
,
"
i
;"
. Składnia
pętli
jest następująca:
# #
Jest ona szczególnie przydatna, gdy korzystamy z licznika, jak w poniższym przykła-
dzie wyświetlającym zestaw znaków ASCII:
< 20
"
#
A1# 1^#HH
*-+ -+ *#
$
Dopuszczalna jest również nieskończona pętla
:
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
221
##
"
$
Język C pozwala używać też pustych instrukcji. Poniższa pętla usuwa z ciągu począt-
kowe znaki odstępu:
#4 UU# HH
#
Warto zwrócić uwagę na średniki odpowiadające inicjalizacji pętli i pustej instrukcji.
Pętla
"
ma konstrukcję nieco prostszą:
Instrukcja lub blok instrukcji (ujęty w nawiasy klamrowe) będą powtarzane do czasu,
gdy wyrażenie warunku przyjmie wartość 
,-./0
. Jeżeli wyrażenie nie jest prawdziwe
jeszcze  przed  wejściem  do  pętli,  instrukcje  nie  będą  wykonywane  w  ogóle.  Jest  to
istotna różnica w stosunku do pętli 
;"
, która zawsze zostaje wykonana co naj-
mniej raz. Jej składnia to:
"
$
#
Instrukcje skoku
Instrukcja
pozwala powrócić z funkcji wykonywanej do funkcji, z której ta zo-
stała  wywołana.  W  zależności  od  zadeklarowanego  typu  wartości  zwracanej  przez
funkcję instrukcja 
może wymagać odpowiedniego parametru:
JYZ'
"
4#
$
lub
5
"
*+=,*#
# 5 92:2
$
Instrukcja
#
służy do wychodzenia z pętli lub instrukcji
"
. W przypadku pę-
tli powoduje to jej przedwczesne zakończenie, jak w poniższym przykładzie:
< 20
"
#
 
222
Hack Wars. Na tropie hakerów
!#1IW#HH
"
!!
#
*-+ *#
$
$
Uzupełnieniem
#
jest polecenie
, wymuszające przeprowadzenie następ-
nej iteracji pętli. Kolejną wykonywaną instrukcją jest w tym przypadku instrukcja pę-
tli (dalsze instrukcje w iterowanym bloku są pomijane). Dostępna jest również funk-
cja  przedwczesnego  zakończenia  wykonywania  programu  — 
. Można za jej
pomocą przekazać wartość zwracaną do programu wywołującego:
#
Continue
Słowo kluczowe
nakazuje skok do instrukcji kontrolnej pętli. W przypadku
pętli zagnieżdżonych jest to instrukcja pętli wewnętrznej (
"
,
+++"
). To spo-
sób  na  łagodne  zakończenie  pętli  jak  w  poniższym  przykładzie,  gdzie  odczytujemy
zapisane w pliku ciągi:
< 20
"
T]Z&4#
4#
? !!@#
*2 ***#
KYZZ
"
*K8 E 2 *#
!#
$
"
!!#
KYZZ
34, 5B43
#
#
$
#
$
W przypadku pętli
instrukcja
powoduje najpierw wykonanie wyrażenia
inkrementacji, a dopiero po nim następuje sprawdzenie warunku zakończenia.
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
223
Wej#cie-wyj#cie
Pobieranie danych
Program  w  języku  C  może  pobierać  dane  z  konsoli  (która  jest  standardowym  urzą-
dzeniem wejściowym), pliku lub portu. Ogólnym poleceniem odczytu danych ze stan-
dardowego  strumienia  wejściowego 
jest
. Skanuje ono po jednym znaku
kolejne pola wejściowe. Podlegają one formatowaniu zgodnie z pierwszym z przekaza-
nych funkcji 
parametrów. Następnie pole zostaje zapisane pod adresem prze-
kazanym jako kolejny parametr wywołania funkcji. Przykładowy program odczytuje
pojedynczą liczbę całkowitą ze strumienia 
:
"
#
*-*.#
$
Warto zwrócić uwagę na operator użyty jako prefiks zmiennej
na liście parametrów
wywołania funkcji
. Funkcja ta zapisuje bowiem wartość pod określonym ad-
resem,  nie  posługując  się  mechanizmem  przypisywania  wartości  zmiennej.  Ciągiem
formatującym jest ciąg znakowy, który może zawierać trzy typy danych: znaki odstępu
(spacja, tabulator, przejście do nowego wiersza), znaki właściwe (wszystkie znaki ASCII
z wyjątkiem znaku %) i specyfikatory formatowania. Specyfikatory te mają następu-
jącą składnię:
-?4@? @?//Z@
Oto przykład:
< 20
"
?A!@#
#
*95*#
*-A!-*.#
*+--*#
$
Zwróćmy uwagę na wiersz
+5
— nakazuje on kompilatorowi prze-
twarzanie pliku nagłówkowego stdio.h, w którym zawarte są prototypy funkcji
i
. Po uruchomieniu tego prostego programu łatwo przekonamy się, że użycie
znaku odstępu przerwie wprowadzanie pierwszego pola danych.
Alternatywną funkcją pobierania danych jest
, odczytująca ciąg znaków ze stru-
mienia
do momentu napotkania znaku nowego wiersza. W ciągu docelowym znak
nowego wiersza zastąpiony zostaje znakiem
73..
. Charakterystyczna dla tej funkcji
jest możliwość odczytywania znaków odstępu. Oto nowa wersja powyższego programu
(korzystająca z 
w miejsce
):
 
224
Hack Wars. Na tropie hakerów
< 20
< 20
< 20
"
?^!@#
4#
?A!@#
#
*+95*#
34L C 43
#
345 V C 43
.? @#
34Y 5_ 6 5C5KYZZ43
4UU"
4!#
#
$
34Z 5 C56C 43
UU#
34L 5 643
#
34, _C 43
4!#
34\ 5C543
#
34,B 543
*+KS-S-*#
$
Wyprowadzanie danych
Podstawową funkcją wyprowadzania danych jest
. Jest ona podobna do
z tą różnicą, że zapisuje dane do standardowego strumienia wyjściowego
.
Funkcja  pobiera  listę  pól  danych  wyjściowych,  odpowiednio  stosuje  specyfikatory
formatowania i wyprowadza wynik. Można stosować takie same przekształcenia for-
matujące jak w przypadku funkcji 
, jak również dodatkowe znaczniki:
;
wyrównuje dane wyjściowe do lewej, uzupełniając je z prawej strony
znakami odstępu międzywyrazowego (spacji),
wymusza poprzedzanie liczb znakiem.
Nieco  odmienna  jest  także  postać  specyfikatora  szerokości.  Jest  on  rozbudowany  o  ele-
ment określający precyzję:
2
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
225
Aby  więc  wyświetlić  liczbę  zmiennoprzecinkową  z  dokładnością  do  trzech  miejsc
dziesiętnych, piszemy:
*-2A*#
Poniżej przedstawiamy listę specjalnych stałych znakowych, które mogą pojawić się
na liście parametrów funkcji 
:
+
nowy wiersz (NL),
+
powrót karetki (CR),
+
tabulator,
+
znak cofania (backspace),
+
znak nowej strony,
+
tabulator pionowy,
++
ukośnik odwrotny (backslash),
+U
apostrof,
+*
cudzysłów,
+R
znak zapytania,
+
ciąg w notacji ósemkowej,
+
ciąg w notacji szesnastkowej.
Kolejny program ilustruje, w jaki sposób wyświetlić liczbę całkowitą w postaci dzie-
siętnej,  szesnastkowej  i  ósemkowej.  Liczba 
<
po znaku procentów (
=
) w instrukcji
nakazuje kompilatorowi dopełnienie wyświetlanej liczby do szerokości co
najmniej czterech cyfr:
349 5 6 43
34 5G543
< 20
"
#
"
*+95 6 ! _E*#
*-*.#
*-!`-!`)-!`*#
$
>!#
$
Do funkcji pokrewnych
należy
, której prototyp ma postać:
T]Z&44 ? 222@#
Jej  zadaniem  jest  przesyłanie  sformatowanych  danych  wyjściowych  do  określonego
strumienia plikowego.
 
226
Hack Wars. Na tropie hakerów
Kolejną tego rodzaju funkcją jest
o prototypie:
44 ? 222@#
Alternatywą dla
jest
, funkcja przesyłająca prosty ciąg do strumienia
. Przesyłany ciąg zostaje automatycznie uzupełniony znakiem nowego wiersza.
Jest to rozwiązanie szybsze od
, jednak jego możliwości są ograniczone.
Bezpo#rednia wymiana danych z konsol*
Do przesyłania i odczytu danych z konsoli (klawiatury i ekranu) można wykorzysty-
wać również bezpośrednie funkcje we-wy. Wyróżnia je litera „c” na początku — od-
powiednikiem 
jest więc
, a odpowiednikiem
— funkcja
. Różnice między funkcjami bezpośredniej wymiany danych a funkcjami
standardowymi są następujące.
J
J
J
J
Nie są wykorzystywane strumienie predefiniowane, nie można więc przekierować
danych przesyłanych funkcjami komunikacji bezpośredniej.
J
J
J
J
Funkcji bezpośrednich nie można przenosić między różnymi systemami
operacyjnymi (m.in. nie można z nich korzystać w programach dla Windows).
J
J
J
J
Funkcje bezpośrednie są szybsze niż standardowe.
J
J
J
J
Nie zapewniają współpracy ze wszystkimi trybami wyświetlania (zwłaszcza
trybami graficznymi VESA).
Wska%niki
Wskaźnik to zmienna, która przechowuje adres elementu danych w pamięci. Deklara-
cja  wskaźnika  jest  podobna  do  deklaracji  zwykłej  zmiennej,  ale  nazwa  poprzedzana
jest znakiem gwiazdki (
), na przykład:
4#
Powyższy wiersz deklaruje zmienną
jako wskaźnik do zmiennej typu
.
Wykorzystanie  wskaźników  dostarcza  szerokich  możliwości,  wymaga  jednak  szcze-
gólnej  uwagi.  Skutki  przypisania  błędnego  adresu  są  najczęściej  nieprzewidywalne.
Oto przykład prostego programu, w którym wykorzystywany jest wskaźnik:
< 20
"
#
4#
345 V 43
!!#
.#
*+M 5 BE--2*#
$
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
227
Wartości wskaźników można zwiększać i zmniejszać, dopuszczalne  są  również  inne
operacje matematyczne. Typowym zastosowaniem wskaźników jest zapewnienie dy-
namicznego przydziału pamięci. W trakcie pracy programu często pojawia się potrze-
ba  przejściowego  (tymczasowego)  zaalokowania  bloku  pamięci.  Korzystamy  wów-
czas z funkcji 
:
" # #
Funkcja
zwraca wskaźnik typu
, co oznacza, że może on wskazywać
dane dowolnego typu —
,
,
itd. W poniższym przykładzie alokujemy
pamięć dla tabeli 1000 liczb całkowitych.
< 20
< 20
"
4#
#
345 V 43
34' 6 !!! C43
34 5 43
34 5 G55 43
!!!4 #
34F5 ;43
KYZZ
"
*+K8E6 !!! 5 B
å *#
!#
$
349 5 BG 43
!# !!!#HH
"
4#
HH#
$
349 BE C 43
!!!#
34,B B 43
!# !!!#HH"
*+& - 5 BE-*4#
HH#
$
349 8 5 643
#
$
 
228
Hack Wars. Na tropie hakerów
Wskaźniki  wykorzystuje  się  również  w  odniesieniu  do  tablic  znaków,  czyli  ciągów
(strings). Ponieważ wszystkie ciągi w programach C kończy bajt o wartości 0, korzy-
stając ze wskaźnika, możemy policzyć znaki w ciągu:
< 20
< 20
"
4#
? !!@#
#
34]5 5CU U43
*'5 *#
34Y BE5C 43
#
34]5 5C; BE43
!#
34M5 43
4
"
HH#
HH#
$
34,B 43
*+X S-* #
$
Wymaganą do zaadresowania 1 MB pamięci 20-bitową liczbę dzieli się na dwie warto-
ści: przesunięcie (offset) i segment (każdy segment to 64 kB). Do przechowywania nu-
merów segmentów pamięci komputer IBM PC wykorzystuje tzw. rejestry segmentowe.
Konsekwencją takiego rozwiązania są w języku C trzy dodatkowe słowa kluczowe:
J
J
J
J
— wskaźniki „bliskie” mają rozmiar 16 bitów i umożliwiają dostęp
do danych bieżącego segmentu,
J
J
J
J
— wskaźniki „dalekie” obejmują wartości określające przesunięcie
i segment, umożliwiając dostęp do dowolnego adresu w pamięci,
J
J
J
J
— wskaźniki „ogromne” to odmiana wskaźników dalekich, zapewniająca
możliwość zwiększania i zmniejszania wartości w całym zakresie 1 MB
(kompilator generuje odpowiedni kod modyfikujący wartość przesunięcia).
Nie  będzie  zapewne  zaskakujące  stwierdzenie,  że  przetwarzanie  programu  korzystają-
cego  ze  wskaźników  typu 
będzie szybsze niż w przypadku programu, w którym
zastosowano wskaźniki
. Wskaźniki
są oczywiście największym obciążeniem.
Kompilatory  C  wyposażone  są  w  makro  zwracające  adres  odpowiadający  podanym
wartościom numeru segmentu i przesunięcia:
4J\(T9 #
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
229
Struktury
Język C oferuje technikę grupowania zmiennych pod jedną nazwą, dostarczając w ten
sposób wygodnego sposobu przechowywania powiązanych ze sobą informacji i struktu-
ralizowania ich. Składnia definicji struktury jest następująca:
"
#
$
2
2
2
$
#
Używanie zmiennych strukturalnych jest niezbędne przy korzystaniu z plików, w któ-
rych występuje uporządkowanie oparte na rekordach danych. W poniższym przykła-
dzie operować będziemy na prostym pliku z listą adresów. Rozpoczniemy od deklara-
cji  struktury 
, złożonej z sześciu pól:
!"#
,
,
,
"$ "!"
,
!
i
:
"
?A!@#
?A!@#
?A!@#
5 ?A!@#
?W@#
? I@#
$
#
Odwołania do pól zmiennej strukturalnej mają postać:
2 #
Nie  ma  ograniczenia  liczby  pól  struktury,  nie  jest  również  wymagane,  aby  typy  pól
były takie same lub podobne, na przyklad:
"
?A!@#
#
4 #
$
#
Jest to poprawna deklaracja struktury obejmująca: pole tablicy znakowej, pole liczby
całkowitej i pole wskaźnika do zmiennej znakowej. Aby przekazać zmienną struktu-
ralną  jako  parametr,  korzystamy  z  jej  adresu  —  poprzedzamy  nazwę  zmiennej  ope-
ratorem 
>
. Oto przykładowy program wykorzystujący struktury w celu wykonania
prostych operacji na pliku listy adresów:
 
230
Hack Wars. Na tropie hakerów
< 20
< 20
< 20
< 20
< 20
< + 20
34 ( 43
< (1I
"
?A!@#
?A!@#
?A!@#
5 ?A!@#
?W@#
? I@#
$
#
#
#
349 543
DXX([&7#
7ZF#
X]F9XD'D#
TD'DZ4#
%&'XD'D#
J&KY#
L9&KXD'D#
F&D[7=#
7ZF
"
#
!# (#HH
**#
$
TD'DZ4
"
*+: S-* #
!#
$
L9&KXD'D
"
34FV 52a8 G243
34a8 G _ 243
*2 *L([X,[/L(D99&KXF(],[]'&#
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
231
"
*2 *L([X,[/L(7[&D'F(],[]'&#
TD'DZ*K8 E *#
$
$
%&'XD'D
"
349 43
7ZF#
*K*#
2#
*+D*#
2#
*+J *#
2 #
*+,5G *#
25 #
*+\ *#
2#
*+K *#
2 #
$
X]F9XD'D
"
34,B 43
?I@#
7ZF#
*K-*2#
*+D-*2#
*+J -*2 #
*+,5G -*25 #
*+\ -*2#
*+K -++*2 #
*,B5&K'&[*#
#
$
DXX([&7
"
34X;C 43
#
.#
TD'DZ*M 8*#
$
F&D[7=
"
 
232
Hack Wars. Na tropie hakerów
? !!@#
#
*,VG *#
#
4 !
#
34M 5C 43
!F&&\(F&'#
"
34M; 5643
.#
0!
"
349 543
2 >KYZZ
#
2 >KYZZ
#
2 >KYZZ
#
25 >KYZZ
#
2 >KYZZ
#
2 >KYZZ
#
$
$
0!#
!#
$
J&KY
"
5#
? !@#
"
7ZF#
*++ + + , 56*#
*+++ + + X5*#
*+++ + + 19 *#
*+++ + + A,5B*#
*+++++*#
#
5 #
5
"
S%&'XD'D#
349;C 5V_ 43
!F&&\(&KX#
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
233
DXX([&7#
#
1SF&D[7=
X]F9XD'D#
"
*K]&MKDZ&M]LK&>*#
*,B5&K'&[*#
#
$
#
AS #
$
$
5>A#
$
"
7ZF#
L9&KXD'D#
J&KY#
$
Pola bitowe
Język C przewiduje możliwość korzystania w strukturach ze zmiennych o rozmiarze
mniejszym niż 8 bitów. Określa się je mianem pól bitowych, a ich rozmiar może być
dowolny, od 1 bitu wzwyż. Deklaracja pola bitowego wygląda następująco:
S #
Przykładem może być deklaracja kilku jednobitowych znaczników stanu:
"
S #
S #
S #
S #
$
#
#
Zmienna
! !#
będzie zajmować w pamięci tylko 4 bity, mimo że składa się z 4 pól,
z których każde dostępne jest jako osobne pole struktury.
Union
Kolejnym  ułatwieniem  języka  C,  pozwalającym  zapewnić  optymalne  wykorzystanie
dostępnej pamięci, jest struktura 
, czyli zbiór zmiennych, współużytkujących je-
den adres pamięci. Oznacza to, oczywiście, że w danym momencie dostępna jest tyl-
ko jedna ze zmiennych składowych. Deklaracja 
ma następującą postać:
 
234
Hack Wars. Na tropie hakerów
"
#
#
2
2
2
#
$#
Wyliczenia
Wyliczenie  (enumeracja)  to  przypisanie  liście  symboli  rosnących  wartości  całkowi-
tych. Wyliczenie deklarujemy:
" $ %#
Przykładem może być definicja listy kolorów:
\LZL[b
"
7MD[Kb
K]&:]&F\]
M]&ZLKb
7M&[,LKb
:[DML,b
aDFKLFMD[b
7]&JKLFMD[b
aDFKLK]&:]&F\]
aDFKLM]&ZLKb
aDFKL7M&[,LKb
MLZ'b
:]DZb
$#
Operacje na plikach
W operacjach dostępu  do  plików  język  C  posługuje  się  buforowanymi  strumieniami
plikowymi. Niektóre z platform języka, jak UNIX i DOS, oferują również niebuforo-
wane uchwyty plików.
Strumienie buforowane
Dostęp do strumieni buforowanych realizowany jest za pośrednictwem wskaźnika do
zmiennej typu 
,6.0
. Ten szczególny typ danych zdefiniowany został w nagłówku st-
dio.h. Aby więc zadeklarować wskaźnik do pliku, wprowadzamy:
< 20
T]Z&4 #
Aby otworzyć strumień, używamy funkcji
. Pobiera ona dwa parametry: na-
zwę otwieranego pliku oraz tryb dostępu. Oto lista trybów dostępu.
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
235
Tryb
Opis
otwórz tylko do odczytu (plik musi istnieć),
utwórz do zapisu; zastąp, jeżeli plik o podanej nazwie istnieje,
otwórz do dołączania danych (dopisywania na końcu pliku); utwórz nowy plik,
jeżeli plik o podanej nazwie nie istnieje,
H
otwórz istniejący plik do odczytu i zapisu (plik musi istnieć),
H
utwórz do odczytu i zapisu; zastąp, jeżeli istnieje,
H
otwórz do czytania i dołączania danych; utwórz nowy plik, jeżeli nie istnieje.
Aby określić tryb tekstowy lub binarny, do opisu trybu można dołączyć
lub
. W przy-
padku  pominięcia  tego  znacznika  strumień  zostanie  otwarty  w  trybie  określanym
zmienną globalną 
)
. Odczyt i zapis danych do strumieni plikowych w trybie tek-
stowym wiąże się z konwersją — podczas zapisu znaki CR i LF zamieniane są na pary
CR LF, a przy odczycie pary CR LF ulegają zamianie na pojedynczy znak LF. Tego
rodzaju operacje nie są wykonywane w trybie binarnym.
Jeżeli funkcja
nie będzie mogła otworzyć pliku, zwróci w miejsce wskaźnika
wartość
73..
(zdefiniowaną w stdio.h). Poniższy program utworzy nowy plik dane.txt
i udostępni go do odczytu i zapisu:
< 20
"
T]Z&4#
*2 **H*#
$
Aby zamknąć strumień, używamy funkcji
, wymagającej podania wskaźnika
do pliku.
#
Jeżeli podczas zamykania strumienia wystąpi błąd, funkcja
zwróci wartość
niezerową  (znacznik  EOF  —  End  Of  File).  Do  przesyłania  i  odbierania  danych  ze
strumieni  służą  cztery  podstawowe  funkcje: 
,
,
i
.
Funkcja
odczytuje pojedynczy znak z określonego strumienia wejściowego
(przekształcany do liczby całkowitej):
T]Z&4#
Jej odwrotnością jest
, zapisująca pojedynczy znak do określonego strumienia
wyjściowego:
T]Z&4#
Funkcja
odczytuje ze strumienia wejściowego ciąg:
4 4 T]Z&4#
 
236
Hack Wars. Na tropie hakerów
Odczyt zostaje przerwany po pobraniu
znaków lub znaku nowego
wiersza (również wstawianego do tablicy). Do odczytanego ciągu
dołączany jest koń-
czący znak
73..! % #? @A*A
. W przypadku wystąpienia błędów
funkcja zwraca
73..
.
Funkcja
zapisuje do strumienia ciąg zakończony znakiem
73..
(inaczej
A*A
):
4 T]Z&4#
Wszystkie opisywane funkcje zwracają w przypadku błędów wartość
0B,
(zdefinio-
waną w stdio.h) z wyjątkiem funkcji
, która w przypadku wystąpienia błędu
zwraca
73..
. Poniższy program tworzy kopię pliku dane.dat, o nazwie dane.old, ilu-
strując zarazem użycie wszystkich czterech funkcji:
< 20
"
T]Z&4#
T]Z&4 #
* 2 ***#
KYZZ
"
*+K8 E 2 *#
!#
$
*2**H*#
KYZZ
"
*+K8 E 2*#
!#
$
349 5 5 5 G43
348 <43
>
#
34M5 43
#
#
!#
$
W kolejnym przykładowym programie używamy funkcji
do kopiowania tekstu
ze strumienia
(zazwyczaj oznacza to znaki wprowadzane z klawiatury) do no-
wego pliku dane.txt:
< 20
"
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
237
T]Z&4#
? !!@#
*2 **H*#
"
#
#
$
4 #
#
$
Swobodny dostp do danych strumieni
Dostęp  swobodny  do  danych  dostarczanych  za  pośrednictwem  strumieni  zapewnia
funkcja 
#
o prototypie:
T]Z&4 #
Funkcja  zmienia  pozycję  wskaźnika  pliku  skojarzonego  ze  strumieniem  otwartym
wcześniej  przez 
. Wskaźnik ustawiany jest na
za (lub przed
w przypadku wartości ujemnej) pozycją
. Tą ostatnią może być początek
pliku, bieżące położenie wskaźnika lub koniec pliku. Pozycje te symbolizują stałe
/00C)/01
,
/00C)D32
i
/00C)07E
. Udaną operację
#
sygnalizuje zwrócenie warto-
ści
. Uzupełnieniem
#
jest funkcja
, zwracająca wartość bieżącej pozy-
cji wskaźnika pliku:
T]Z&4#
Funkcja  zwraca  pozycję  wskaźnika  pliku,  określoną  jako  ilość  bajtów  od  początku
pliku, lub 
;
w przypadku błędu.
Uchwyty
Uchwyty plików (handles) otwiera funkcja
o prototypie:
4 &? @#
Udaną operację sygnalizuje zwrócenie numeru uchwytu. W pozostałych przypadkach
zwracane jest 
F
. Na wartość
składają się połączone bitową operacją OR stałe
symboliczne, odpowiadające deklaracjom w pliku fcntl.h. Różnią się one w zalezności
od kompilatora. Do typowych należą:
L(D99&KX
przed każdym zapisem wskaźnik pliku będzie ustawiany na końcu pliku,
L(7[&D'
jeżeli plik nie istnieje, zostanie utworzony,
L('[YK7
obcina istniejący plik do długości 0 bajtów,
L(&)7Z
używane w połączeniu z
B)D20-1,
L(:]KD[b
otwiera plik w trybie binarnym,
L('&)'
otwiera plik w trybie tekstowym.
 
238
Hack Wars. Na tropie hakerów
Po przypisaniu uchwytu pliku za pomocą polecenia
można korzystać z funkcji
i
"
. Prototyp
jest następujący:
% 4 #
Funkcja podejmuje próbę odczytu podanej liczby bajtów i zwraca liczbę bajtów fak-
tycznie pobranych przez uchwyt pliku. Odczytane dane umieszczane są w bloku pa-
mięci  określonym  parametrem 
. Funkcja
działa podobnie, nie różni się
również jej prototyp i sposób generowania wartości zwracanej. Zapisuje ona podaną
ilość  bajtów  z  określonego  wskaźnikiem  bloku  pamięci.  Pliki  otwierane  funkcją
zamykamy funkcją
:
% #
Funkcja
zwraca
w przypadku operacji udanej, a
F
w przypadku wystąpie-
nia błędów.
Dostęp swobodny zapewnia funkcja
#
, bardzo podobna do
#
, ale pobie-
rająca jako parametr numer uchwytu, a nie wskaźnik strumienia
,6.0
. W poniższym
przykładzie wykorzystujemy uchwyt pliku do zapisu danych z
(czyli klawiatu-
ry) do nowego pliku o nazwie dane.txt:
< 20
< 20
< + 20
"
#
? !!@#
*2 *L([X,[/L(7[&D'/L('[YK7F(],[]'&#
"
#
. #
$
4 #
#
$
Przegl*d funkcji plikowych
Norma  ANSI  definiuje  związane  z  plikami  operacje  we-wy  przy  użyciu  strumieni,
opisując różnorodne funkcje. Prototyp funkcji 
ma postać:
T]Z&4 4 4#
Funkcja podejmuje próbę otwarcia strumienia łączącego z plikiem o podanej nazwie
w  określonym  trybie.  Udana  operacja  kończy  się  zwróceniem  wskaźnika  typu 
,6.0
.
W przypadku niepowodzenia funkcji zwraca
73..
. Na wcześniejszych stronach przed-
stawiony został opis parametru
.
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
239
Funkcja
służy do zamykania strumienia otwartego wcześniejszym wywoła-
niem
:
T]Z&4#
Udana operacja
kończy się opróżnieniem wszystkich buforów pliku i zwró-
ceniem wartości
. W przypadku błędów zwracana jest wartość
0B,
.
Wiele komputerów korzysta z buforowanego dostępu do plików. Oznacza to, że dane,
zapisywane do strumienia, wstępnie umieszczane są w pamięci, a faktyczny zapis na-
stępuje  dopiero  po  przekroczeniu  pewnej  granicznej  ilości  bajtów.  Jeżeli  w  czasie,
gdy dane nie zostały jeszcze faktycznie zapisane do strumienia, nastąpi awaria zasila-
nia,  dane  zostaną  utracone.  Zabezpiecza  przed  tym  funkcja 
, wymuszająca
zapisanie wszystkich danych oczekujących:
T]Z&4#
Jeżeli wywołanie
jest udane, związane ze strumieniem bufory zostają opróż-
nione i zwracana jest wartość
. W przypadku błędów funkcja zwraca wartość
0B,
.
Kolejną funkcją jest
zwracająca lokalizację wskaźnika pliku:
T]Z&4#
Funkcja zwraca przesunięcie wskaźnika pliku w stosunku do początku pliku lub
F.
w przypadku błędów. Przesunięcie wskaźnika pliku do nowej pozycji umożliwia
#
:
T]Z&4 #
Funkcja podejmuje próbę przesunięcia wskaźnika pliku o
bajtów od pozycji
, określonej jedną ze stałych:
F&&\(F&'
początek pliku,
F&&\(7Y[
bieżąca pozycja wskaźnika pliku,
F&&\(&KX
koniec pliku.
Przesunięcie (
) może być wartością dodatnią (przesuwanie wskaźnika w stronę
końca  pliku)  lub  ujemną  (przesuwanie  wskaźnika  w  stronę  początku  pliku).  Aby
szybko  przenieść  wskaźnik  do  początku  pliku  i  usunąć  wcześniejsze  odwołania  do
błędów, C dostarcza funkcji 
"
:
T]Z&4#
Funkcja ta działa podobnie jak
#&.&/00C)/01
. Jednak
#
usuwa znacz-
nik
0B,
, a
" #"
wszystkie sygnały błędów. Informacje o błędach funk-
cji plikowych można pobrać przy użyciu funkcji
:
T]Z&4#
Funkcja zwraca wartość niezerową, jeżeli w określonym strumieniu wystąpił błąd. Po
sprawdzeniu  wartości 
należy zadbać o usunięcie sygnałów błędów za po-
mocą funkcji
:
T]Z&4#
 
240
Hack Wars. Na tropie hakerów
Sprawdzenie,  czy  spełniony  jest  warunek  osiągnięcia  końca  pliku,  realizuje  predefi-
niowane makro 
:
T]Z&4#
Makro zwraca wartość niezerową, gdy dla danego strumienia stwierdzono osiągnięcie
końca pliku. W pozostałych przypadkach zwracaną wartością jest 
.
Dostępnych  jest  kilka  funkcji  realizujących  odczyt  danych  ze  strumienia  plikowego.
Pojedyncze znaki można odczytywać funkcją 
:
T]Z&4#
zwraca wartość ASCII pobranego znaku lub znak
0B,
w przypadku wystąpie-
nia błędu. Odczyt ciągu danych umożliwia funkcja
, odczytująca ciąg zakoń-
czony znakiem nowego wiersza:
4 ' T]Z&4#
W wyniku udanego wywołania funkcji w zmiennej
umieszczany jest ciąg zakoń-
czony znakiem nowego wiersza lub zawierający
znaków. Funkcja zachowuje
kończący ciąg znak nowego wiersza, dołączając do ciągu
bajt
73..
. W przypadku
nieudanego  wywołania  zwracany  jest  wskaźnik  pusty.  Ciągi  zapisujemy  do  strumie-
nia funkcją 
:
4 T]Z&4#
Funkcja
zapisuje wszystkie znaki ciągu
, z wyjątkiem końcowego bajtu
73..
, do strumienia
. Standardowo funkcja zwraca ostatni zapisany znak, a w przy-
padku wystąpienia błędów —
0B,
. Dostępna jest również funkcja zapisująca do stru-
mienia pojedynczy znak
:
T]Z&4#
Funkcja zwraca zapisany znak lub, w przypadku wystąpienia błędów, znak
0B,
.
Aby odczytać ze strumienia duży blok danych lub rekord, można posłużyć się funkcją
:
( 4( ( T]Z&4#
Funkcja podejmuje próbę odczytu
elementów, z których każdy ma długość
,
ze strumienia plikowego
do bloku pamięci określonego wskaźnikiem
. Aby
ustalić, czy operacja przebiegła bez zakłóceń, korzystamy z funkcji
.
Siostrzaną funkcją
jest
"
:
( 4( ( T]Z&4#
Funkcja zapisuje
elementów o długości
z obszaru pamięci określonego
wskaźnikiem
do strumienia
.
Funkcja
umożliwia odczyt danych formatowanych:
T]Z&4 4?222@#
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
241
Funkcja zwraca liczbę faktycznie odczytanych pól, a
0B,
w przypadku końca pliku.
Poniższy przykład ilustruje użyteczność funkcji
podczas odczytywania ze
strumienia liczb:
< 20
"
T]Z&4#
#
#
#
#
#
? !!@#
*2 **H*#
>
"
*K8 E *#
!#
$
* 1A`I+*, +**#
#
"
*:;C * #
#
$
#
"
*:;C5 * #
#
$
*------*.. ... #
"
*:;C * #
#
$
*+T 5G;------* #
$
Jak łatwo zauważyć, zapis formatowanych danych realizuje funkcja
. Gdy
pojawia  się  potrzeba  zapisania  położenia  wskaźnika  pliku  i  późniejszego  jego  przy-
wrócenia, można skorzystać z funkcji 
i
. Pierwsza z nich odczy-
tuje bieżącą pozycję wskaźnika pliku:
T]Z&4( 4 #
 
242
Hack Wars. Na tropie hakerów
Funkcja
ustawia wskaźniki pliku na określonej pozycji:
T]Z&4 ( 4 #
Typ
)
zdefiniowany został w nagłówku stdio.h. Funkcje te są wygodniejsze
w użyciu niż
i
#
.
Z otwartym już strumieniem można skojarzyć nowy plik. Umożliwia to funkcja
:
T]Z&4 4 4T]Z&4#
Funkcja zamyka strumień istniejący i podejmuje próbę jego ponownego otwarcia przy
użyciu  podanej  nazwy  pliku.  Znajduje  to  zastosowanie  przy  przekierowywaniu  stru-
mieni  predefiniowanych 
,
i
do pliku lub urządzenia. Przykłado-
wo, gdy pojawia się potrzeba przekierowania wszystkich danych wyjściowych kiero-
wanych do 
na drukarkę, można użyć polecenia:
*Z9' *** #
Predefiniowane strumienie we-wy
Wstępnie zdefiniowane zostały trzy strumienie we-wy:
,
i
. Do-
myślnie
i
odpowiadają klawiaturze i monitorowi. Na wielu platformach,
w  tym  systemów  DOS  i  UNIX,  dostępna  jest  możliwość  ich  przekierowania.  Stru-
mień 
domyślnie powiązany jest z monitorem (wyświetlaczem). Praktyka jego
przekierowywania  nie  jest  raczej  stosowana.  Jego  podstawowym  zadaniem  jest  za-
pewnienie możliwości wyświetlania komunikatów błędów, nawet w sytuacji gdy po-
wiązanie standardowego wyjścia (
) zostało zmienione:
*\ ;6* #
Funkcje
i
przekazują dane do strumienia
. Funkcje
i
pobierają dane ze strumienia
. Przekierowanie tych strumieni zmienia
sposób działania funkcji.
Jako  przykład  plikowych  operacji  we-wy  na  platformie  PC,  korzystających  z  możli-
wości przekierowania strumieni, przedstawimy  prosty  program  przesyłający  do  stru-
mienia 
zawartość określonego pliku, przedstawioną jako wartości szesnastko-
we. Polecenie w postaci:
( 20(5B2
pozwoli zmienić domyślne powiązanie strumienia
z monitorem.
< 20
< 20
< 20
< 20
4?@
"
#
?1!@#
#
#
#
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
243
>1
"
*+:cdX29;;S +* #
#
$
? @L([XLKZb#
"
*+:cdX2K8 E-+*? @#
#
$
*+MD,D['Lef9Z]\Y-++* ? @#
!#
"
34,; 43
!1!#
349 43
( . W#
34! < ;C43
#
34,V 43
*-!W-!I*#
H W#
34,V B 5 G 43
!# W#HH
*-!1* ?@#
34,V BDF7]] 5 G 43
!# W#HH
"
?@0A .. ?@ 1^
*-* ?@#
*2* #
$
34M_43
*+* #
$
34_43
!#
$
 
244
Hack Wars. Na tropie hakerów
Ci"gi
Język C należy do najlepiej wyposażonych w funkcje obsługi ciągów pośród uniwer-
salnych  języków  programowania.  Ciąg  to  jednowymiarowa  tablica  znaków  zakoń-
czona  bajtem  zerowym.  Ciągi  można  inicjować  dwoma  sposobami.  Pierwszym  jest
nadanie im stałej wartości w kodzie programu:
"
4*F I*#
?@*9 *#
!#
$
Drugi to utworzenie ciągu w czasie wykonywania programu za pomocą funkcji
%
:
4 4 4"#
Funkcja
%
kopiuje ciąg źródłowy do lokalizacji docelowej, na przykład:
< 20
"
?I!@#
*FF *#
*+, BEC UU -*#
!#
$
Język C umożliwia bezpośredni dostęp do każdego bajtu ciągu:
< 20
"
?I!@#
*FF *#
*+, BEC UU -*#
34M C 5 CUU43
?!@UU#
*+, BEC UU -*#
!#
$
Niektóre kompilatory C wyposażone zostały w funkcje konwersji ciągów do wielkich
i małych liter, nie obejmuje ich jednak norma ANSI. W specyfikacji pojawiają się za
to funkcje 
i
"
, zwracające pojedynczy znak ( w postaci wartości
)
zamieniony na literę wielką lub małą. Łatwo na tej podstawie utworzyć własne funk-
cje konwersji ciągów:
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
245
< 20
4
"
4#
#
4
"
40gN..4 11
4 4#
HH#
$
$
4
"
4#
#
4
"
40WI..4g!
4 4#
HH#
$
$
"
?I!@#
*FF *#
*+, BEC UU -*#
#
*+, BEC UU -*#
#
*+, BEC UU -*#
!#
$
' ; 2T 5 C ;
5C55 EVG;2\5 6
56 B A1 5 G865C
;2aB 5 65 8 C
C586 2, hFi
hAi2, 5 ; 6
; 2S
4
"
40gN..4 11
4 4#
HH#
 
246
Hack Wars. Na tropie hakerów
$
4
"
40WI..4g!
4 4#
HH#
$
X ;92:22
W przeciwieństwie do innych języków programowania C nie narzuca ograniczenia dłu-
gości ciągu. Jednak w przypadku niektórych procesorów (CPU) pojawia się ogranicze-
nie wielkości bloku pamięci. Oto prosty program odwracający kolejność znaków w ciągu:
< 20
< 20
4 4
"
34L5BEGC 5C543
34_KYZZ43
4#
4#
#
34Y VUU C 43
H #
34M VC C 43
#
34M43
0
"
4#
44#
4 #
#
HH#
$
#
$
"
? !!@#
4#
*'5 C*#
#
*+-*#
$
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
247
strtok()
Funkcja
#
jest istotną funkcją języka C, służącą do wyłączania fragmentów
ciągu. Stosuje się ją, gdy poszczególne podciągi rozdzielone są znanymi ograniczni-
kami, na przykład przecinkami:
< 20
< 20
"
?I!@#
4#
*7M&[,LKb9LJD[Dj7ML,bklc'bM]&ZLKbK]&:]&F\]*#
**#
"
#
KYZZ**#
$#
$
Program można oprzeć też na pętli
:
< 20
< 20
"
?I!@#
4#
*7M&[,LKb9LJD[Dj7ML,bklc'bM]&ZLKbK]&:]&F\]*#
**## KYZZ**
"
#
$#
$
W pierwszym wywołaniu funkcji
#
podajemy nazwę zmiennej ciągu oraz
ogranicznik.  Funkcja  zwraca  wówczas  wskaźnik  do  początku  pierwszego  podciągu
i zastępuje pierwszy ogranicznik zerem. Kolejne wywołania 
#
wykonywane są
w pętli. Pierwszym parametrem jest wówczas
73..
, a funkcja zwraca kolejne podcią-
gi. Ponieważ dopuszczalne jest podanie listy ograniczników, funkcja
#
może
posłużyć do utworzenia prostego programu zliczającego słowa:
< 20
< 20
< 20
4?@
"
T]Z&4#
?1IW@#
 
248
Hack Wars. Na tropie hakerów
4#
#
>1
"
*+:cdX29;;S +* #
!#
$
34L G 43
? @**#
34FV ; 43
>
"
*+:cdX2K8 E VG;+* #
!#
$
34]5 543
!#
"
34L 5 43
1II#
34FV C; ;C <43
//
#
34M; 43
34F;G865 43
34+ +#S2>R543
*+ +#S2>R*#
"
HH#
KYZZ*+ +#S2>R*#
$
$
>..>#
34L _2:;CR43
"
*+:;C VG;+* #
#
!#
$
34L _<43
34, 6;G43
*+9--;G;+*? @#
#
$
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
249
Zamiana liczb na ci*gi i ci*gów na liczby
Wszystkie  kompilatory  C  zapewniają  możliwość  konwertowania  liczb  na  ciągi  przy
użyciu takich funkcji jak 
. Funkcja ta ma jednak wiele zastosowań, co po-
woduje, że jest rozbudowana i mało wydajna. Może ją zastępować funkcja
61B/
,
korzystająca z dwóch parametrów: liczby całkowitej ze znakiem i wskaźnika do ciągu
znakowego. Funkcja kopiuje liczbę do określonego wskaźnikiem miejsca w pamięci.
Podobnie jak 
, funkcja
61B/
nie sprawdza, czy ciąg docelowy ma wystar-
czającą do przechowania wyniku konwersji długość. Oto przykładowa funkcja, która
kopiuje liczbę 
do ciągu znakowego.
]'LF4
"
34M_6 C 6; CCG43
?g@" !!!!!!!! !!!!!!! !!!!!! !!!!! !!!! !!! !! ! $#
#
34FV43
!
"
4 HHUU#
34M_ BE 6C43
!#
$
!#g#HH
"
0 ?@
"
4 HHU!UH3 ?@#
- ?@#
$
$
4 U+!U#
_;_ ;
å 68 592:2
#
$
98;;5 5 5C6
å 2985 CC5692:2S
]'LF4
"
34M_6 C 6; CCG43
?g@" !!!!!!!! !!!!!!! !!!!!! !!!!! !!!! !!! !! ! $#
#
!#33 C C
34FV43
!
"
4 HHUU#
HH#
34M_ BE 6C43
!#
$
 
250
Hack Wars. Na tropie hakerów
!#g#HH
"
HH#
4 HHU!UH3 ?@#
- ?@#
$
4 U+!U#
#33G VC C
!#
4 UU336 C 5B5
HH#
4 U!U"335C
HH#
HH#
$
4 >U+!U"
4 4 #33C 5 8 C
HH#
$
4 U+!U#
#
$
Język C oferuje dwie funkcje do zamiany ciągów znakowych na liczby zmiennoprze-
cinkowe: 
i
. Prototyp funkcji
ma postać:
4 #
a prototyp funkcji
:
4 44 #
Obie funkcje przeglądają ciąg i przeprowadzają konwersję aż do momentu natrafienia
na niezrozumiały znak. Różnica między nimi polega na tym, że 
pobiera do-
datkowy parametr, wskaźnik
ustawiany na pierwszy znak ciągu, który nie został
objęty  konwersją.  Znacznie  zwiększa  to  wygodę  sprawdzania  poprawności  wykona-
nia operacji.
Aby zamienić ciąg na wartość całkowitą, można użyć funkcji
:
4 #
Należy pamiętać, że funkcja
nie zapewnia żadnej kontroli przepełnienia zmien-
nej.  Nie  jest  zdefiniowana  wartość  zwracana  w  takiej  sytuacji.  W  podobny  sposób
działa  funkcja 
, zwracająca wartość
. Odpowiedniki z dodatkowym para-
metrem noszą nazwy
i
.
Obsługa tekstu
Człowiek  zapisuje  informacje  jako  pewien  „tekst”,  złożony  ze  słów,  liczb  i  znaków
przestankowych. Słowa złożone są z liter wielkich i małych, odpowiednio do wyma-
gań  gramatyki.  Wszystko  to  sprawia,  że  komputerowe  przetwarzanie  tekstu  nie  jest
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
251
zadaniem  prostym.  Norma  ANSI  definiuje  wiele  funkcji  przetwarzania  ciągów  zna-
kowych,  które  z  natury  rozpoznają  wielkość  liter.  Oznacza  to,  że  litera  „A”  rozpo-
znawana  jest  jako  różna  od  „a”.  Jest  to  pierwsze  zagadnienie,  którego  rozwiązanie
musi  znaleźć  programista  pracujący  nad  programem  przetwarzającym  tekst.  Na  szczę-
ście, zarówno kompilatory Borlanda, jak i Microsoftu wyposażone zostały w funkcje
obsługi ciągów, które nie rozpoznają wielkości liter.
Taką odmianą funkcji
jest
, a
—
. Gdy jed-
nak  pojawia  się  kwestia  przenośności  kodu,  niezbędna  jest  zgodność  z  ANSI  C,  co
pociąga za sobą napisanie własnych funkcji.
Poniżej przedstawiamy prostą implementację nierozróżniającej wielkości liter odmia-
ny funkcji 
. Tworzy ona kopie ciągów, zamienia je na wielkie litery i wyko-
nuje standardową operację
. Pozwala to określić poszukiwaną wartość prze-
sunięcia i utworzyć wskaźnik do ciągu źródłowego.
4 4 41
"
? !!!@#
1? !!!@#
4#
#
11#
#
1#
1#
H #
KYZZ#
$
Kolejna funkcja przegląda ciąg
, wyszukując słowo podane jako
G
. Aby funkcja
zwróciła wartość
1230
, znalezione musi zostać odrębne słowo, a nie jedynie sekwen-
cja znaków. Wykorzystujemy przygotowaną wcześniej funkcję
.
(4 41
"
34 BEC5815 ; 43
4#
4m#
#
!#
m #
"
34Z 5 C5G1 43
m1#
"
 
252
Hack Wars. Na tropie hakerów
34M43
#
0
"
34FVC43
4 0UDU..4 UU
!#
$
34K 5C 43
H 1#
4
"
34FVC43
40UDU..4UU
!#
$
$
m#
$
..>#
#
$
Szerokie zastosowanie znajdzie kilka dalszych prostych funkcji znakowych.
obcina ciąg znakowy:
4
"
34L U UGC UU43
? @!#
$
usuwa końcowe znaki spacji (odstępu międzywyrazowego) w ciągu:
4
"
34 5_43
4#
. ? @#
4A1..0
4!#
$
zmienia długość ciągu:
4
"
34M; BEC ;C5C 5C43
0!
H H #
"
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
253
! #
H H #
$
$
umieszcza jeden ciąg w innym:
44m
"
34, CmC 43
m#
m m#
$
zastępuje wszystkie wystąpienia pewnego podciągu innym podciągiem:
44 41
"
34M 6 5 C C143
4#
#
"
!#
#
"
34Y _C43
! #
34, C43
1#
#
$
$
#
$
Data i godzina
Język C wyposażony jest w funkcję
, która odczytuje zegar systemowy kom-
putera i podaje informację o dacie i godzinie w postaci liczby sekund, która upłynęła
od północy 1 stycznia 1970 roku. Wartość ta może zostać zamieniona na czytelny dla
człowieka ciąg znaków za pomocą funkcji 
:
< 20
< 20
"
34F 243
( #
349 66 43
KYZZ#
*:8C S-+* . #
$
 
254
Hack Wars. Na tropie hakerów
Na ciąg zwracany przez
składa się siedem pól:
J
J
J
J
dzień tygodnia,
J
J
J
J
miesiąc roku,
J
J
J
J
dzień miesiąca,
J
J
J
J
godzina,
J
J
J
J
minuty,
J
J
J
J
sekundy,
J
J
J
J
rok.
Uzupełnieniem jest znak nowego wiersza i końcowe 0. Ponieważ pola mają stałą sze-
rokość,  ciąg  zwracany  przez 
idealnie nadaje się do operacji wymagających
wyodrębnienia  elementów  daty  lub  godziny.  W  poniższym  programie  definiujemy
strukturę 
!
oraz funkcję
!)!
, której zadaniem jest wypełnienie
struktury treścią pól ciągu
:
< 20
< 20
< 20
"
(#34J 43
(#34%43
(#34F 43
$#
( 4
"
( #
?1W@#
4 #
349 66 43
KYZZ#
349 66 C 43
. #
34L 5 43
? g@!#
. ? @#
349 5C 5 43
*-1S-1S-1*. 0(. 0(. 0(#
$
"
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
255
#
(. #
*+a -!1S-!1S-!1*. 2(. 2(. 2(#
$
Norma  ANSI  przewidziała  również  funkcję  konwertującą  wartość  zwracaną  przez
funkcję 
do postaci struktury. Przedstawiony poniżej przykład zawiera deklara-
cję struktury
z nagłówka
+
:
< 20
< 20
"
( #
4 #
349 43
KYZZ#
34M_ BE 6 43
. #
*+a -!1S-!1S-!1* 0 ( 0 ( 0 (#
!#
$
Struktura
(zawarta w pliku
) ma następującą postać:
"
(#
(#
( #
(#
(#
(#
(#
(#
( #
$#
' 8 E6BC 5 5 5 8
å ;G2, 5 5 B ;C2
å J85C E 5 G;G6
å BE 6I 92:2
Liczniki czasu
Programy często korzystają z możliwości pobrania daty i czasu z nieulotnej pamięci
RAM komputera. Norma ANSI przewiduje kilka różnych funkcji, które mogą zostać
do tego celu wykorzystane. Pierwszą jest funkcja 
, zwracająca liczbę sekund od
1 stycznia 1970 roku:
( ( 4#
 
256
Hack Wars. Na tropie hakerów
Funkcja wypełnia przekazaną jej jako parametr zmienną typu
)
jeśli nie jest to
73..
, zwracając tę samą wartość również jako wartość wyjściową. Można więc wywo-
ływać funkcję
z parametrem
73..
i korzystać z wartości zwracanej:
< 20
"
( #
KYZZ#
$
Funkcja
zamienia strukturę
na 26-znakowy ciąg (przedstawiony przy
opisie funkcji
):
4 4 #
Funkcja
zamienia wartość czasu (zwracaną przez
) na 26-znakowy ciąg:
< 20
< 20
< 20
"
( #
?A!@#
KYZZ#
. #
$
Kolejna funkcja,
, zwraca, liczoną w sekundach, różnicę między dwoma
wartościami typu
)
. Służy więc do wyznaczania ilości czasu, jaki upłynął mię-
dzy dwoma zdarzeniami, czasu wykonywania funkcji lub generowania przerw w pra-
cy programu, na przykład:
< 20
< 20
X&ZDb
"
( #
KYZZ#
KYZZH
#
$
"
*+[222I *#
X&ZDbI#
*+L_2*#
$
 
Rozdział 6.
¨
¨
¨
¨ Podstawy programowania dla hakerów
257
Funkcja
zamienia lokalną wartość czasu
)
na wartość GMT o postaci
struktury
. Działanie tej funkcji zależy od ustawienia globalnej zmiennej strefy cza-
sowej. Struktura
została wstępnie zdefiniowana w nagłówku
+
. Przedstawili-
śmy ją kilka stron wcześniej.
"
(#
(#
( #
(#
(#
(#
(#
(#
( #
$#
Element struktury
) %
przechowuje dzień miesiąca (od 1 do 31), a
)" %
— dzień
tygodnia (gdzie niedzieli odpowiada 0). Czas jest mierzony od 1900 roku. Wartość
)
to znacznik, który informuje o tym, czy stosowany jest czas letni. Stosowa-
ne  nazwy  struktury  i  jej  elementów  mogą  różnić  się  w  zależności  od  kompilatora,
jednak sama struktura zasadniczo pozostaje niezmieniona.
Funkcja
#
zamienia strukturę
na wartość
)
, uzupełniając wartości pól
)" %
i
)% %
:
( 4#
W kolejnym przykładzie umożliwiamy wprowadzanie daty i używamy funkcji
#
do  ustalenia  dnia  tygodnia.  Należy  pamiętać,  że  funkcje  związane  z  czasem  rozpo-
znają wyłącznie daty późniejsze niż 1 stycznia 1970:
< 20
< 20
< 20
"
#
#
? !!@#
4#
4?@
"***;** **B** **C ** **
å gN!*$#
"
!#
*+,V 633*#
g #
*3*#
>KYZZ
2 ( #
#
 
258
Hack Wars. Na tropie hakerów
KYZZ*3*#
>KYZZ
2 ( #
#
KYZZ*3*#
>KYZZ
2 ( #
#
#
$
>#
2 ( !#
2 (!#
2 ( #
2 ( #
34' _ 43
.
2 (N#
*'_ -+*? 2 (@#
$
Funkcja
#
zapewnia również wprowadzenie odpowiednich poprawek dla warto-
ści przekraczających swój dopuszczalny zakres. Można to wykorzystać do ustalenia do-
kładnej daty, odległej o 
dni:
< 20
< 20
< 20
"
4 #
( 5#
5 KYZZ#
.5#
0 (H !#
#
0 (0gg
0 (- !!#
5CB ;6 5
å ;C; g!!5 ; 8gg 92:2
*M6E 6-!13-!13-!1+* 0 ( 0 (H
å 0 (#
$