2008 07 Hakowanie GG

background image

30

HAKIN9

ATAK

7-8/2008

G

adu–gadu jest komunikatorem
internetowym, który zrzesza już prawie
6 milionów użytkowników. Swoją

popularność zawdzięcza prostocie działania,
intuicyjnej obsłudze i przede wszystkim
pochodzeniu – jest to produkt made in Poland.
Żółte słoneczko jest znakiem rozpoznawalnym
chyba przez każdego polskiego internautę.
Nie jest to jednak aplikacja wolna od błędów
– są one normalnym zjawiskiem, ściśle
powiązanym z tworzeniem oprogramowania
komputerowego. Błąd odkryty w Gadu–Gadu
7.7 pozwala na na wykonanie dowolnego kodu
na komputerze osoby, która korzysta z tego
programu. Tkwi on w obsłudze emotikonów
– plik

emots.txt

, zawierający emotikony,

podczas wczytywania łańcuchów znakowych
nie sprawdza ich długości. Możliwe jest zatem
wykonanie przepełnienia bufora (aczkolwiek nie
w klasyczny sposób). Opisywana podatność
dotyczy Gadu–Gadu w wersji 7.7 build 3669. Jak
to zrobić, jak wykorzystać tę podatność – o tym
traktuje niniejszy artykuł.

Początki Gadu – Gadu

Najpopularniejszy polski komunikator
internetowy, Gadu–Gadu, liczy sobie już ładne
parę lat – a dokładniej osiem. Za narodziny
Gadu–Gadu uważa się datę 15 sierpnia 2000
roku. Ceny połączeń internetowych w Polsce
spadają, Internet staje się medium dostępnym
niemal dla każdego. Ludzie zaczynają korzystać

KONRAD ZUWAŁA

Z ARTYKUŁU

DOWIESZ SIĘ

jak działa protokół Gadu–Gadu,

na czym polega obsługa

wyjątków w C++,

jak napisać exploit dla aplikacji

Gadu–Gadu.

CO POWINIENEŚ

WIEDZIEĆ

czym jest Gadu–Gadu,

znać podstawy programowania

w C/C++ i asemblerze,

na czym polega przepełnienie

bufora.

z możliwości komunikacyjnych, jakie zapewnia
im Sieć. Szybko jednak dostrzegają lukę – niszę,
którą wykorzystał właśnie komunikator GG. Otóż
brakuje im prostego, przejrzystego programu,
który umożliwiałby rozmowy ze znajomymi.
Program w dodatku powinien być bezpłatny.
Gadu–Gadu idealnie wpasowuje się w lukę,
komunikator lawinowo zyskuje popularność. Już
pierwszego tygodnia, gdy ukazał się on w Sieci,
pobrało go ponad dziesięć tysięcy osób – co
jest świetnym wynikiem, zważywszy, że był on
wtedy nikomu nie znanym, nowym programem.
Gadu–Gadu musiał walczyć o popularność,
a konkurencję miał silną. Nie brak w końcu
produktów zagranicznych, o ugruntowanej
już pozycji, w dodatku również dostępnych
bezpłatnie. Co jednak zadecydowało?

Gadu Gadu oferuje nam prosty, przejrzysty

interfejs. Pisanie i wysyłanie wiadomości nie
wymaga od użytkownika wiele wysiłku. Często
nie jest nawet konieczne używanie myszki
– wystarczy przysłowiowy Enter, aby wiadomość
trafiła do adresata. Okienko rozmowy jest
przejrzyste, a sam interfejs programu nie budzi
większych zastrzeżeń. No i przede wszystkim
program jest po polsku, co wtedy było nie lada
rarytasem – nie zapominajmy, że w 2000 roku
Internet w Polsce dopiero raczkował, niewiele
aplikacji było dostępnych w rodzimym języku.

Rosnąca popularność komunikatora niesie

ze sobą pewne problemy. Serwery często
bywają przeciążone bądź wręcz niedostępne.

Stopień trudności

Hakowanie

Gadu – Gadu

Gadu–Gadu to z pewnością najpopularniejszy w Polsce

komunikator internetowy. Niemal każdy kiedyś się z nim zetknął,

najczęściej aby porozmawiać ze znajomymi. Jednak nawet tak

popularna aplikacja nie ustrzeże się błędów – czy możemy czuć

się bezpieczni z Gadu–Gadu?

background image

31

HAKIN9

HAKOWANIE GADU – GADU

7-8/2008

Wiąże się to z trudnościami w połączeniu
i opóźnieniami w dostarczaniu
wiadomości. Problemy nasilają się wraz
ze wzrostem ilości użytkowników, który na
stronie producenta określony jest mianem
lawinowego. Trudności te nie stanowią
jednak dyskomfortu dla kolejnych rzesz
użytkowników. Ćwierć miliona, pół miliona,
milion – liczby zdają się nie mieć końca.
Aż dochodzimy do dnia dzisiejszego i
mamy niespełna (a może już ponad?)
sześć milionów wiernych użytkowników.

Możliwości komunikatora

Dzisiejsze komunikatory internetowe
oferują swoim użytkownikom znacznie
więcej aniżeli tylko możliwość rozmowy
tekstowej. Choć ta w Gadu–Gadu jest
niezwykle prosta – okienko jest schludne
i przejrzyste. Widać, do czego służy każdy
przycisk, nie ma większych problemów
z nawigacją wewnątrz programu. Można
pisać szybko i wygodnie – słowem
dokładnie tak, jak być powinno.

Rozmowa tekstowa to jednak nie

wszystko, na co pozwala nam ten
program. Jeśli ktoś nie lubi pisać, można
porozmawiać bez użycia klawiatury.
Rozmowy głosowe, bo o nich mowa,
są stosunkowo świeżym dodatkiem.
Dodatkowo możemy za pomocą połączeń
bezpośrednich przesyłać pliki zupełnie
tak, jak za pomocą programu P2P (ang.
peer to peer). Pliki graficzne możemy
wygodnie umieścić w okienku programu –
pod warunkiem, iż mają one odpowiedni
rozmiar, gdyż zbyt duża grafika nie może
zostać przesłana z użyciem serwera
(rozmowy na GG prowadzone są poprzez
serwer, który pośredniczy w konwersacji).

Ostatnią z wyraźnie rzucających się

w oczy funkcji jest możliwość słuchania
radia za pomocą komunikatora
– mamy do wyboru kilka kanałów,
każdy o innym profilu muzycznym,
co z pewnością zadowala wielu
wybrednych melomanów. Do dyspozycji
mamy jeszcze portal użytkowników i
pomoc techniczną. Jednym słowem
– pięknie. Czy komunikator ten nie
ma wad? Ma – chodzi oczywiście o
bezpieczeństwo. Nie jest to oczywiście
domena tylko tej aplikacji, albowiem
większość programów komputerowych,
które są dostępne na rynku, zawiera
jakieś błędy bezpieczeństwa. Są one

ustawicznie likwidowane przez twórców
oprogramowania, co powoduje, że rzadko
kiedy istnieje możliwość exploitacji danej
podatności. Jednak użytkownicy Gadu–
Gadu często zapominają o regularnej
aktualizacji posiadanego komunikatora
– przyczynia się do tego również brak
funkcji automatycznej aktualizacji,
która bez jakiejkolwiek ingerencji ze
strony użytkownika dokonywałaby
systematycznego uaktualnienia
najważniejszych komponentów programu.
A tak – musimy to zrobić sami,
pobierając najnowsza wersję ze strony
producenta.

Jest to tylko jedna z nielicznych wad

komunikatora, bo nie jest on od nich
niestety wolny. Przede wszystkim serwery
są często przeciążone, co powoduje
niekiedy niemożność podłączenia się
do sieci. Dodatkowo, w najnowszych
wersjach usunięto możliwość rozmowy
tekstowej z użyciem połączeń
bezpośrednich – sprawiając, iż cały ruch
sieciowy transferowany jest poprzez
dedykowane do tego serwery. Może to
budzić obawy niektórych użytkowników co
do poufności ich konwersacji.

Kryptografia również nie należy do

mocnych stron aplikacji. Ustawienie opcji
pozwalającej na zapamiętanie hasła w
programie, tak, aby logować się do sieci
bez jego podawania, jest dość ryzykowne.
Hasło jest bowiem przechowywane w
praktycznie niezaszyfrowanej postaci w
pliku na komputerze użytkownika. Gdy
jakaś niepowołana osoba uzyska dostęp
do zawartości naszego dysku twardego,
ma możliwość odszyfrowania takiego
hasła (w Sieci dostępnych jest wiele
programów, które służą do tego celu).

Sama rozmowa również nie jest

szyfrowana. Brak szyfrowania SSL, które
jest w dzisiejszych czasach standardem
poufności przesyłanej informacji, jest
poważną wadą. Umożliwia to bowiem
przechwycenie naszej rozmowy każdej
osobie, która umie obsługiwać program
sniffujący. A przecież narzędzi takich
nie brakuje – warto wspomnieć choćby
tcpdumpa, który jest chyba sztandarowym
narzędziem badającym ruch w sieci.
Pojawiły się nawet specjalistyczne sniffery,
których użycie nie wymaga większej
wiedzy. Nasłuchują one tylko na portach
obsługiwanych przez komunikator.

Pozwala to niemal każdemu oglądać treść
naszych rozmów.

Błąd, który odkryto w Gadu–Gadu,

pozwala na wykonanie dowolnego kodu
na komputerze ofiary. Zanim jednak
przejdziemy do jego omawiania, warto
zapoznać się z samym protokołem
używanym przez Gadu–Gadu – należy
wiedzieć, z czym mamy do czynienia.

Protokół Gadu – Gadu

Jak każda aplikacja działająca w
Internecie, Gadu–Gadu potrzebuje
jakiegoś protokołu, z pomocą którego
może przesyłać dane przez sieć. Warto
więc wiedzieć, jak wygląda ten protokół,
aby mieć ogólne pojęcie o działaniu
programu. Oczywiście nie będzie to
bardzo szczegółowy opis, jeśli jednak
Czytelnik jest takowym zainteresowany,
adres odpowiedniej witryny internetowej
znajduje się w Ramce W Sieci.

Gadu–Gadu korzysta z protokołu TCP/

IP. Jest to bowiem protokół gwarantujący
poprawność przesyłanych danych. A
przecież niezawodność i pewność, że

Rysunek 1.

Interfejs programu Gadu–

Gadu

background image

ATAK

32

HAKIN9 7-8/2008

HAKOWANIE GADU – GADU

33

HAKIN9

7-8/2008

wiadomość dotrze do odbiorcy jest
chyba najważniejszą cechą każdego
komunikatora.

Każdy pakiet wysyłany przez

komunikator zawiera dwa pola, które
zawsze znajdują się w tym samym
miejscu – na początku pakietu. Można
je zatem nazywać nagłówkiem, słowo to
doskonale bowiem oddaje charakter tych
danych. Pola te prezentuje Listing 1.

Nazwy zmiennych są chyba intuicyjne,

toteż nie jest potrzebne ich tłumaczenie
– typ to po prostu rodzaj pakietu, jaki
wysyłamy, natomiast dlugość to rozmiar
w bajtach pozostałej części pakietu (czyli
rozmiar pakietu bez rozmiaru nagłówka).

Ale zanim połączymy się z siecią

Gadu–Gadu i zaczniemy rozmawiać z
którymś z naszych znajomych, musimy
najpierw połączyć się z serwerem.
Serwerów jest jednak kilka, toteż musimy
w jakiś sposób otrzymać informacje, z
którym z nich mamy się połączyć. W tym
celu wysyłamy żądanie HTTP do strony
odpowiedzialnej za przydzielenie nam
serwera. Odpowiedni kod zaprezentowany
jest na Listingu 2.

Takiego połączenia możemy dokonać

za pomocą zwykłego programu, takiego
jak

telnet

czy

netcat

. Wystarczy, że

połączymy się na 80 porcie ze stroną

appmsg.gadu–gadu.pl

i prześlemy

odpowiednie żądanie – takie, jak na
Listingu 2. Wartości zapisane wielkimi
literami oznaczają zmienne przesyłane
do strony – są to kolejno: nasz numer
GG, wersja komunikatora,

FORMAT

określa sposób przesyłania wiadomości
(czy ma być to czysty tekst, czy też

użyty zostanie HTML),

MESSAGE

zaś to

numer wiadomości systemowej, jaką
otrzymaliśmy poprzednio od Gadu–Gadu,
gdy nawiązywaliśmy próbę połączenia.
Wreszcie

BROWSER

to wersja przeglądarki,

np.

Mozilla 4.0 (compatible; MSIE

5.0, Windows NT)

.

Strona zwróci nam adres IP serwera,

z którym mamy się połączyć, dodając
do tego numer wiadomości systemowej
(tej, którą podawaliśmy w żądaniu HTTP)
oraz port, na którym mamy dokonać
połączenia z serwerem (zwykle jest to
port 8074).

Teraz pora na zalogowanie się do

sieci GG. W tym celu serwer najpierw
wysyła do nas pakiet, liczbę całkowitą

int

, która jest zwana ziarnem. Ziarno

odpowiada za wygenerowanie skrótu
CRC hasła. Przed ziarnem otrzymujemy
jednak – na samym początku połączenia

– pakiet powitalny. Ilustruje to Listing 3.

Aby zalogować się do sieci, potrzebny

jest szereg informacji. Przede wszystkim
są to nasz numer GG oraz hasło.
Niezbędne będą również m.in. dane
dotyczące wersji używanego klienta.
I znów z pomocą przychodzi nam
odpowiednia struktura, która skupia
w sobie wszelkie dane wymagane do
zalogowania naszego klienta w sieci.
Prezentuje ją Listing 5.

Struktura Logowanie jest pakietem,

który należy wysłać do odpowiedniego
serwera – po to, by ten dopuścił
naszego klienta do działania w sieci
GG. Pierwsze pole, uin, to nic innego jak
używany przez nas numer Gadu–Gadu.
Dwa następne pola powiązane są z
hasłem – pierwsze,

hash _ typ

, to wybór

algorytmu szyfrowania hasła. Dostępne
są dwa algorytmy: CRC i SHA1. Algorytm

Listing 1.

Nagłówek Gadu–Gadu

struct

NaglowekGadu

{

int

typ

;

int

dlugosc

;

}

;

Listing 2.

Żądanie HTTP wysyłane do serwera przydzielającego adresy IP serwerów GG

GET

/

appsvc

/

appmsg4

.

asp

?

fmnumber

=

NUMBER

&

version

=

VERSION

&

fmt

=

FORMAT

&

lastmsg

=

MESSAGE

Accept

:

image

/

gif

,

image

/

jpeg

,

image

/

pjpeg

, ...

Accept

Language

:

pl

User

Agent

:

BROWSER

Pragma

:

no

cache

Host

:

appmsg

.

gadu

gadu

.

pl

Listing 3.

Inicjacja połączenia z serwerem GG

#define PAKIET_POWITALNY 0x0001

struct

Powitalna

{

int

ziarno

;

}

;

Listing 4.

Logowanie komunikatora do sieci

#define LOGUJ 0x0019

struct

Logowanie

{

int

uin

;

char

hash_typ

;

char

hash

[

64

];

int

status

;

int

wersja

;

char

nieznany1

;

int

lokalny_ip

;

short

lokalny_port

;

int

zewnetrzny_ip

;

short

port_zewnetrzny

;

char

rozmiar_obrazka

;

char

nieznany2

;

char

opis

[];

int

czas

;

}

;

Rysunek 2.

Okno rozmowy programu

Gadu–Gadu

background image

ATAK

32

HAKIN9 7-8/2008

HAKOWANIE GADU – GADU

33

HAKIN9

7-8/2008

CRC jest uważany za słabszy, albowiem
przy danym ziarnie (pakiet z serwera
będący liczbą całkowitą) możliwe jest
wygenerowanie tego samego hasha
dla dwóch różnych haseł. Prowadzi
to do możliwości zalogowania się z
czyjegoś numeru GG bez znajomości
jego hasła. Jest to jednak raczej kwestia
szczęścia i wielu godzin żmudnych analiz
generowanych hashy. Listing 6. można
potraktować jako ciekawostkę – jest na
nim przedstawiony algorytm generowania
hasha hasła CRC32. Następne pola, czyli
status oraz wersja oznaczają kolejno:

status ustawiany po połączeniu się z
serwerem (np. zaraz wracam) i wersję
używanego klienta GG. Pola nieznany1
i nieznany2 nie są jeszcze poznane.
Znaczenia reszty pól chyba nie trzeba
tłumaczyć, albowiem ich nazwy mówią
same za siebie.

Ostatnią rzeczą, którą przydałoby

się wiedzieć o protokole, jest sposób,
w jaki wysyłana jest wiadomość. W
końcu właśnie to jest najważniejsze
w komunikatorze internetowym, stąd
koniecznym jest poznanie tego procesu
od środka. W zrozumieniu organizacji

procesu wysyłania wiadomości pomoże z
pewnością struktura zaprezentowana na
Listingu 7.

Interesującym jest tylko pole

klasaWiadomosci – znaczenie
pozostałych jest raczej oczywiste. Klasa
wiadomości określa, czy wysyłana przez
nas wiadomość ma ukazać się w nowym,
czy też w istniejącym już okienku. Jest
to sposób, w jaki komunikator rozróżnia
sesje prowadzone w tym samym czasie
– dzięki czemu wie, kiedy inicjowana
jest nowa rozmowa, a kiedy informacja
dotyczy już istniejącej konwersacji.

Z naszego punktu widzenia

ważnym jest przesyłanie emotikonów.
Jak zatem odbywa się to w protokole
Gadu–Gadu? Emotikony są zwykłymi
plikami graficznymi (z rozszerzeniem gif).
Odpowiednie struktury odpowiedzialne za
przesyłanie obrazka zaprezentowane są
na Listingu 8.

Struktury te odpowiadają za

wyznaczenie parametrów przesyłanego
obrazka. Kolejne zmienne określają sumę
kontrolną i rozmiar obrazka. Obrazek
wysyłany w oknie komunikatora jest
traktowany jak specjalny tekst, albowiem
jest on de facto jednym z atrybutów
tekstu.

Co się dzieje, gdy przesyłane są

emotikony? Cóż, wszystko odbywa się
w ten sam sposób. Różnica polega na
tym, że nie przesyłamy obrazka, tylko jest
on wczytywany z dysku użytkownika. W

Listing 5.

Funkcja generująca hash hasła

int

hashHasla

(

unsigned

char

*

haslo

,

unsigned

int

ziarno

)

{

unsigned

int

x

,

y

,

z

;

y

=

ziarno

;

for

(

x

=

0

;

*

haslo

;

haslo

++)

{

x

=

(

x

&

0xffffff00

)

|

*

haslo

;

y

^

=

x

;

y

+=

x

;

x

<<=

8

;

y

^

=

x

;

x

<<=

8

;

y

=

x

;

x

<<=

8

;

y

^

=

x

;

z

=

y

&

0x1f

;

y

=

(

y

<<

z

)

|

(

y

>>

(

32

z

));

}

return

y

;

}

Listing 6.

Struktura odpowiadająca za wysyłanie wiadomości

#define GG_SEND_MSG 0x000b

struct

wiadomosc

{

int

numerOdbiorcy

;

int

sekwencja

;

int

klasaWiadomosci

;

char

tresc

[];

}

;

Listing 7.

Struktury odpowiedzialne za przesyłanie obrazków

struct

atrybutyTekstu

{

short

pozycja

;

char

czcionka

;

char

kolorCzcionki

[

3

];

struct

obrazekGG

image

;

}

;

struct

obrazekGG

{

short

nieznany1

;

int

rozmiar

;

int

sumaKontrolna

;

}

;

struct

odpowiedzObrazka

{

char

flaga

;

int

rozmiar

;

int

sumaKontrolna

;

char

nazwaPliku

[];

char

zawartoscObrazka

[];

}

;

Listing 8.

Fragment pliku emots.txt

":)"

,

"usmiech.gif"

,

"_usmiech.gif"

":>"

,

"ostr.gif"

,

"_ostr.gif"

":]"

,

"kwadr.gif"

,

"_kwadr.gif"

":("

,

"smutny.gif"

,

"_smutny.gif"

":|"

,

"yyyy.gif"

,

"_yyyy.gif"

"<uoee>"

,

"uoeee.gif"

,

"_uoeee.gif"

"<lol>"

,

"haha.gif"

,

"_haha.gif"

"<rotfl>"

,

"ROTFL.gif"

,

"_ROTFL.gif"

";)"

,

"oczko.gif"

,

"_oczko.gif"

":P"

,

"jezyk.gif"

,

"_jezyk.gif"

";P"

,

"jezyk_oko.gif"

,

"_jezyk_oko.gif"

"<radocha>"

,

"zacieszacz.gif"

,

"_

zacieszacz.gif"

"<luzik>"

,

"luzik.gif"

,

"_luzik.gif"

"<figielek>"

,

"figielek.gif"

,

"_figielek.gif"

"<milczek>"

,

"milczek.gif"

,

"_milczek.gif"

"<stres>"

,

"stres.gif"

,

"_stres.gif"

"<nerwus>"

,

"nerwus.gif"

,

"_nerwus.gif"

":["

,

"zly.gif"

,

"_zly.gif"

"<zalamka>"

,

"zalamka.gif"

,

"_zalamka.gif"

"<wnerw>"

,

"wnerw.gif"

,

"_wnerw.gif"

"<glupek>"

,

"glupek.gif"

,

"_glupek.gif"

background image

ATAK

34

HAKIN9 7-8/2008

tym celu skanowany jest odpowiedni plik,

emots.txt

, następnie w miejsce danego

ciągu znaków podstawiany jest obrazek.
Jednak kod odpowiedzialny za wykonanie
tych czynności jest błędny – nie
sprawdza on długości wczytywanych
łańcuchów. Wykorzystamy ten fakt w
naszym exploicie.

Skoro znamy podstawy protokołu,

wiemy jak wygląda logowanie do sieci i
wysyłanie wiadomości, czas zabrać się za
wykorzystanie tej wiedzy do zbudowania
exploita. Przyjrzyjmy się najpierw
błędom, jakie dotychczas pojawiały się w
komunikatorze.

Przegląd błędów

Gadu–Gadu, jak każdy program, nie jest
wolne od błędów. W tej części tekstu
przyjrzymy się niektórym z nich, aby lepiej
przygotować się do zbudowania exploita,
wykorzystującego najnowszy błąd odkryty
w popularnym komunikatorze.

Pierwszym z ataków, jakie omówimy,

będzie atak DoS na komunikator. Otóż,
w poprzednich wersjach komunikatora
możliwe było unieruchomienie
programu poprzez wysłanie specjalnie
spreparowanego obrazka. Gdy obrazek
zaczynał się od specjalnych słów, np.
AUX: , wywoływany był błąd jego obsługi,
co zawieszało cały wątek odpowiedzialny
za tę czynność. Mało tego, gdy nazwa
pliku graficznego zaczynała się od LPT:
, możliwe było przesłanie go do drukarki
użytkownika komunikatora – mało
śmieszny kawał.

Pozostaniemy ciągle przy

obrazkach. Gdy nazwa pliku obrazka
miała dostatecznie dużą długość,
możliwe było wykonanie ataku DoS
poprzez przepełnienie bufora zmiennej
obsługującej nazwy plików graficznych.
Jeśli długość nazwy pliku zawierała
się w przedziale od 192 do 200 bajtów

(jeden znak to jeden bajt), wywoływało
to przepełnienie bufora na stosie,
powodując błąd programu i jego
terminację.

Połączenia bezpośrednie również

były przyczyną powstania podatności
umożliwiającej atak DoS. Przesyłanie
specjalnie spreparowanych pakietów
mogło doprowadzić do konsumpcji
ogromnej ilości pamięci przez program
kliencki, co w konsekwencji mogło
zmusić użytkownika nawet do restartu
systemu. Brak pamięci powodował
bowiem znaczne zwolnienie działania
komputera, praca na nim stawała
się więc niezwykle mało komfortowa.
Mamy więc do czynienia z atakiem typu
Denial of Service, którego celem jest
unieruchomienie maszyny ofiary, bądź
przynajmniej części oprogramowania na
niej działającego.

Ostatnim błędem, o którym

wspomnimy, była luka wynikająca z
rejestracji rozszerzenia gg: w systemie.
Gdy użytkownik wchodził na stronę
internetową, na której znajdowały
się odnośniki w rodzaju gg:1234567,
wszystko było w porządku. Sprawa
zaczynała się nieco komplikować, gdy po
literach gg: znajdowało się coś zupełnie
innego, aniżeli poprawny identyfikator.
Mogło to doprowadzić nawet do utraty
plików konfiguracyjnych komunikatora

– co zapewne nie należało do
najprzyjemniejszych doświadczeń.

Jak widać, najczęściej błędy

komunikatora umożliwiały atak typu
DoS. Zabicie procesu komunikatora czy
unieruchomienie systemu były tym, co
mogło spotkać użytkownika Gadu–Gadu.
Błąd, który opiszemy w dalszej części
artykułu, pozwala na coś znacznie
więcej: możemy wykonać dowolny kod na
komputerze ofiary, czyli przejąć nad nim
pełną kontrolę. Jest to więc podatność
o wiele groźniejsza aniżeli te, które
dotychczas odnajdowano w programie
klienckim.

Emitokony – exploit

dla Gadu – Gadu

Skończmy wreszcie z tą aurą tajemnicy.
Mamy już odpowiednie przygotowanie
teoretyczne, zajmijmy się zatem
budowaniem właściwego exploita dla
Gadu–Gadu.

Błąd, który umożliwia wykonanie

zdalnego kodu, związany jest z
emotikonami. Przyjrzymy się zatem
strukturze plików komunikatora (Rysunek 4).

Dla nas szczególnie interesujące

będą katalogi zawierające emotikony.
Czym są emotikony? Otóż, gdy
rozmawiamy z użyciem Gadu–Gadu,
możliwe jest używanie animowanych
minek w okienku rozmowy. Są to właśnie

Rysunek 4.

Struktura pików komunikatora – plik emots.txt

Rysunek 3.

Ryzykowne zapamiętanie

hasła w programie

background image

HAKOWANIE GADU – GADU

35

HAKIN9

7-8/2008

emotikony. Odpowiednia kombinacja
znaków, na przykład buźki :) czy :
P
, powoduje wczytanie określonego
pliku graficznego i wstawienie go do
okna rozmowy. Plik ten jest animacją
GIF, zawierającą treść adekwatną
do wpisanego ciągu znaków, np.
uśmiechającą się twarz.

Dla nas istotną kwestią jest to,

skąd komunikator umie powiązać plik z
konkretnym ciągiem znaków. Słowem,
skąd wie, że :) to uśmieszek, a ;( to płacz.
W tym celu w katalogach zawierających
animacje GIF z emotikonami
umieszczono plik tekstowy, nazwany
emots.txt. Zawartość pliku przedstawiona
jest na Listingu 9.

Jak widać na Listingu 9, każdemu

specjalnemu ciągowi znaków
przypisywana jest konkretna nazwa
pliku, co powoduje wstawienie go w
miejsce tegoż ciągu w oknie rozmowy
komunikatora.

Na czym polega błąd? Otóż, wstawiając

odpowiedni ciąg znaków do pliku emots.txt,
możemy dokonać przepełnienia bufora.
Funkcja, która kopiuje dane z tego pliku, nie
sprawdza długości pobieranych łańcuchów.
Powoduje to możliwość przepełnienia
bufora na stosie. Nie będzie to jednak
klasyczne przepełnienie bufora – nie
nadpiszemy bowiem adresu powrotu
z funkcji. Nasze wysiłki skupią się na
nadpisaniu struktury SEH (ang. Structured
Exception Handling
, Strukturalna Obsługa

Wyjątków). Otóż, gdy w Gadu–Gadu
wystąpi błąd, zgłaszany jest wyjątek. Wyjątki
charakteryzują się tym, że trzeba je w jakiś
sposób obsłużyć – napisać odpowiedni
kod, odpowiedzialny za wykonanie
działania mającego na celu wyjście z
awaryjnej sytuacji, jaką jest niepoprawne
zachowanie się programu. Musimy więc
przyjrzeć się strukturze obsługi wyjątków,
ona bowiem będzie naszym celem. Należy
nadpisać kod funkcji obsługującej wyjątki.
Konsekwencją tego będzie możliwość
wykonania ataku DoS lub, co jest bardziej
wyrafinowaną metodą, wykonanie
dowolnego kodu na maszynie ofiary.

SEH – obsługa wyjątków

Język C cechuje dość poważna wada. Ma
on problemy z obsługą wyjątków. Tworząc
procedury obsługujące wyjątki sprawiamy,
iż nasz kod jest mało przejrzysty. Jak
bowiem obsłużyć niepoprawne zachowanie
funkcji w języku C? Sposobów na to nie
mamy zbyt wiele. W zasadzie są trzy
główne techniki, które można nazwać jakąś
obsługą sytuacji awaryjnych.

Pierwszym, i chyba

najpopularniejszym, sposobem jest
zwracanie odpowiedniej wartości przez
funkcję. Wyobraźmy sobie funkcję, której
zadaniem jest dzielenie liczb. Niech
funkcja wygląda następująco:

double dzielenie(double liczba1,

double liczba2)

Funkcja dzieli

liczbę1

przez

liczbę2

,

zwracając wynik takiej operacji. Ale co
zrobimy w przypadku, gdy użytkownik
wprowadzi niepoprawne dane? Na
przykład liczba2 będzie zerem. Jak wiemy
z matematyki, dzielenie przez zero jest
niemożliwe (wynik takiej operacji będzie
dążył do nieskończoności, jednak dla liczb
doskonale bliskich zeru, nie będących
zerem). Co wtedy? Gdy nie przewidzimy
takiej sytuacji, program może ulec
zawieszeniu, może wygenerować błąd
systemowy i zostać zakończonym. Musimy
więc przygotować jakąś obsługę tego
kodu. W języku C moglibyśmy zrobić to na
trzy sposoby:

• sprawdzamy, czy dzielnik nie jest

zerem, jeśli tak – to generujemy
odpowiedni komunikat,
implementujemy odpowiednie
zachowanie funkcji, bądź po prostu
zwracamy odpowiednią wartość;

• jeśli dzielnik jest zerem, możemy ustawić

globalną zmienną odpowiedzialną za
kod błędu, następnie w dalszej części
programu dokonamy jej sprawdzenia;

• najbardziej wyrafinowanym

sposobem jest użycie funkcji

setjmp()

i

longjmp()

. Funkcje te

powodują kolejno: zapisanie stanu
komputera w specjalnym buforze
(zapisywane są rejestry, zawartość
stosu, wskaźnik stosu – słowem
stan programu z danego momentu

R

E

K

L

A

M

A

background image

ATAK

36

HAKIN9 7-8/2008

HAKOWANIE GADU – GADU

37

HAKIN9

7-8/2008

wykonywania) oraz przeniesie
programu w poprzedni (zapisany)
stan. Zatem jeśli dzielnik jest zerem,
możemy przenieść program w
stan sprzed podania niepoprawnej
wartości zmiennej, dając tym
samym użytkownikowi możliwość
jej ponownego, poprawnego już
podania;

• w celu obsługi błędu możemy

użyć jeszcze biblioteki sygnałów.
Gdy program napotka określoną
sytuację (np. dzielnik jest zerem),
generuje sygnał, który jest następnie
obsługiwany przez odpowiednią
funkcję. Jednak w dużych projektach
jest to rozwiązanie mało komfortowe,
ponieważ numery sygnałów (każde
zdarzenie generuje sygnał o
określonym numerze) mogą się ze
sobą pokrywać, wprowadzając tym
samym chaos do projektu.

Wyraźnie widać, że w tej kwestii język C
jest wysoce niedoskonały. Język C++
to swoisty krok do przodu w stosunku
do C, toteż likwiduje ten problem,
wprowadzając obsługę wyjątków. Jak
mówi sama nazwa – SEH – tworzona
jest odpowiednia struktura/klasa, która
jest odpowiedzialna za obsługę wyjątków.

Zawiera ona niezbędne informacje
dotyczące konkretnego błędu. Gdy
występuje błąd, opisany w strukturze
wyjątek jest wyrzucany (ang. throw) i
następnie przechwytywany (ang. catch)
przez odpowiednią procedurę obsługi
wyjątków.

Mechanizm ten jest użyty w

komunikatorze Gadu–Gadu. Gdy coś
pójdzie nie tak, generowany jest wyjątek,
który następnie przejmowany jest przez
odpowiednią funkcję. Ta, po określeniu
typu błędu, ma za zadanie wykonać
odpowiednie działania. Co się jednak
stanie, gdy nadpiszemy tę funkcję i
wywołamy wyjątek? No właśnie, tu
otwierają się dla nas różne możliwości...

Budujemy exploit

Nasz exploit powinien wykonywać kod na
komputerze ofiary. W tym celu musimy
podmienić plik zawierający emotikony i
czekać, aż ofiara użyje odpowiedniego
emotikona. Jak to zrobimy – zależy
tylko od nas. Możemy namówić
użytkownika do ściągnięcia pliku,
zaproponować nowy zestaw emotikon.
Z pewnością, aby namówić ofiarę do
wykorzystania dostarczonego przez
nas pliku, przydatne będą umiejętności
socjotechniczne.

Zajmijmy się teraz stroną techniczną

exploita. Na Listingu 10. widzimy kod, w
którym znaleziono błąd. Wyraźnie widać,
że występują tam pętle kopiujące dane
do bufora. Nie jest jednak sprawdzana
długość kopiowanych łańcuchów.
To otwiera nam pierwszą możliwość

– możemy wykonać atak typu DoS.
Zamieniając ciąg _usmiech.gif na
1080 liter A, możliwe jest zmuszenie
programu do wygenerowania
komunikatu o błędzie i zakończenia
działania. Dzieje się tak, ponieważ
zawartość pliku jest przepisywana do
odpowiedniego miejsca w pamięci, bez
uprzedniej weryfikacji rozmiaru danych.
Nadpisujemy tym samym procedury
obsługi wyjątków, powodując przerwanie
działania aplikacji i wygenerowanie
komunikatu o błędzie.

Zwykle w takiej sytuacji nasuwa się

pomysł na przepełnienie bufora metodą
nadpisania adresu powrotu z funkcji.
W tym przypadku nie jest to jednak
możliwe. Dlaczego? Otóż Gadu–Gadu
używa zaawansowanej obsługi wyjątków.
Gdy chcemy nadpisać adres powrotu
z funkcji, nadpisujemy przy tym wiele
różnych zmiennych, co powoduje w tym
przypadku wyrzucenie wyjątku. Jest to
zaś niczym innym, jak przekazaniem
sterowania nad programem do innej jego
części. Nasz kod jest więc omijany i nie
zostaje wykonany. Proste, acz skuteczne
zabezpieczenie.

Musimy więc stworzyć takiego

exploita, aby nie nadpisywał adresu
powrotnego z funkcji. Musi być bardziej
wyrafinowany – jego celem powinna stać
się SEH – struktura odpowiedzialna za
obsługę wyjątków. Tylko w ten sposób
możemy zmusić program do wykonania
naszego kodu.

Dysponujemy odpowiednią ilością

danych do zbudowania exploita.

Listing 9.

Wadliwy kod –

przepełniamy bufor

.

text

:

00443E37

loc_443E37

:

.

text

:

00443E37

cmp

al

, '

"'

.text:00443E39 jz short loc_443E48
.text:00443E3B mov [ecx], al.
.text:00443E3D inc ecx
.text:00443E3E inc edi
.text:00443E3F mov [ebp–18h], edi
.text:00443E42
.text:00443E42 loc_443E42:
.text:00443E42 mov al, [edi]
.text:00443E44 cmp al, ' '
.text:00443E46 jnb short loc_443E37
(…)
.text:00443E87 loc_443E87:
.text:00443E87 cmp cl, '"

'

.

text

:

00443

E8A

jz

short

loc_443E9F

.

text

:

00443

E8C

mov

[

eax

]

,

cl

.

text

:

00443

E8E

inc

eax

.

text

:

00443E8F

inc

edi

.

text

:

00443E90

.

text

:

00443E90

loc_443E90

:

.

text

:

00443E90

mov

cl

,

[

edi

]

.

text

:

00443E92

cmp

cl

, ' '

.

text

:

00443E95

mov

[

ebp

–18

h

]

,

edi

.

text

:

00443E98

jnb

short

loc_443E87

Rysunek 5.

Emotikony

background image

ATAK

36

HAKIN9 7-8/2008

HAKOWANIE GADU – GADU

37

HAKIN9

7-8/2008

Możemy wywołać wyjątek w programie,
a następnie nadpisać procedurę jego
obsługi. Zlokalizowanie procedury obsługi
wyjątków nie jest trudne – debugger
wyraźnie pokazuje jej lokalizację pod
adresem w pamięci

fs:[0]

, czyli

0x0032FCA8

. Bufor zaczyna się pod

adresem

0x0032F868

. Różnica tych

dwóch wartości daje nam dokładnie
1088 bajtów. Nasz plik winien więc
wyglądać następująco:

• buźka, np. „:)”,
• „1095 liter A”,
• „szelkod”.

Dlaczego 1095 liter A, skoro różnica
wyniosła tylko 1088 bajtów? Cóż, po
prostu musimy zacząć nadpisywanie
struktury od pewnego jej miejsca, nie od
samego początku. Stąd wynika, iż 1088
liter to za mało – testy autorów exploita
(www.vexillium.org) wykazały, iż właśnie ta
wartość jest odpowiednia.

Prowadząc dalszą analizę możemy

się przekonać, że to jeszcze nie wszystko.
Program nie wywołał wyjątku – nie
pokazało się okienko z błędem. Autorzy
zauważyli, iż wynika to z działania
systemu operacyjnego. Nie każdy uchwyt
procesu, który ustawimy, jest przez niego
wywoływany. Do sprawdzenia, czy dany
uchwyt może być wywołany, służy funkcja

RtlIsValidHandler()

, znajdująca się

w bibliotece

ntdll.dll

. Sprawdza ona

poprawność adresów, zapewniając
niejakie zabezpieczenie przed wykonaniem
niewłaściwego kodu. Jeśli wartość rejestru
AL po wywołaniu tej funkcji wynosi 1,
wtedy kod może zostać uruchomiony
– adres jest poprawny i instrukcje pod nim
zamieszczone są dozwolone do wykonania.
Musimy więc, po każdym wywołaniu tej
funkcji, zmienić wartość rejestru AL na 1
– tak, aby możliwe było wykonanie naszego
szelkodu.

Podsumujmy więc posiadane

informacje. Musimy stworzyć ciąg

ponad tysiąca liter A, wstawić tam adres
w pamięci, pod który przekierujemy
wykonanie programu oraz umieścić
szelkod. Adres ten powinien byś jakimś
adresem, z którego korzysta Gadu–
Gadu. Może to być na przykład funkcja
znajdująca się w jednej z bibliotek, z
których korzysta aplikacja. Pozwoli to na
poprawne przejście przez sito funkcji

RtlIsValidHandler()

, ustawiając

wartość rejestru AL procesora na 1
– wszystko wyglądać będzie na poprawny
kod. Autorzy exploita proponują użyć
w tym celu biblioteki

LIBEAY32.dll

.

Tworzymy więc szelkod i konstruujemy
odpowiednio exploit. Gotowy plik

emots.txt

powinien zatem wyglądać

następująco:

• :)
• 967 liter A,
• szelkod,
• 37 bajtów danych,

instrukcja przeskakująca do adresu w
pamięci, pod którym będzie znajdować
się szelkod (czyli adres początku
bufora+967),

• adres kodu w bibliotece LIBEAY32.DLL

– aby wszystko się wykonało,

• jakieś dane.

Stronę autora exploita oraz dokładny opis
procesu znajdowania błędu i budowania
exploita możemy znaleźć w Ramce W
Sieci.

Podsumowanie

Gadu–Gadu, najpopularniejszy polski
komunikator internetowy, nie jest
pozbawiony wad. Wystarczy przekonać
naiwnego użytkownika do stworzenia
nowego folderu z emotikonami i
umieszczenia w nim pliku

emots.txt

z exploitem. Należy jednak pamiętać,
że stałe, systematyczne aktualizowanie
programu ustrzeże Czytelnika przed tego
typu atakami.

Rysunek 6.

Gadu–Gadu pod debuggerem

W Sieci

http://vexillium.org – strona autora exploita, doskonale tłumacząca zasadę jego działania,
http://gadu–gadu.pl – strona domowa komunikatora Gadu–Gadu,
http://ekg.chmurka.net/docs/protocol.html – szczegółowy opis protokołu Gadu–Gadu,
http://msdn2.microsoft.com/en–us/library/ms680657(VS.85).aspx – opis SEH.

Konrad Zuwała

Autor zajmuje się bezpieczeństwem aplikacji

internetowych oraz szeroko rozumianą ochroną

systemów komputerowych. W wolnych chwilach

programuje (głównie C/C++, PHP) oraz zarządza

portalem internetowym.

Kontakt z autorem: kzuwala@poczta.onet.pl


Wyszukiwarka

Podobne podstrony:
Hard Rock Cafe 2008 07
PiKI 2008 07 08
LM 2008 07
2008 07 08 Superkaramba [Poczatkujacy]
Elektronika dla wszystkich 2008 07
2008 07 08 Bezpieczeństwo sieci Wi Fi [Bezpieczenstwo]
PP 2008 07
2008 07 09 rozp w sprawie ogolnych przepisow Bhp
Hard Rock Cafe 2008 07
2008 07 31 Gretkowska na Woodstock
laboratorium artykul 2008
laboratorium artykul 2008 07 19617
2008 07 Bezpieczne instytucje finansowe
Elektronika dla wszystkich 2008 07
2008 07 Wirtualny pulpit Windows

więcej podobnych podstron