Video of the week

This is a must-watch video about one of us trying to reach the stars :-)

Well done #HRejterzy

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?

Jeśli chciałbyś zobaczyć to bardziej głęboko to dorzucam screen z wireshark'a dla pełnego obrazu. Zwróć uwagę na dwa zielone obszary z napisami connect i shutdown, wszystko co inne jest nieistotne. Zwróć uwagę na kolejność flag w kolejnych pakietach.

 wireshark connect

connect
 

Jeszczę tylko zrzut z konsoli:

  1. flash@flash-laptop:~/Ubuntu/socket/tcpscan$ g++ -g tcpscan.cpp -o tcpscan
  2. flash@flash-laptop:~/Ubuntu/socket/tcpscan$ ./tcpscan 127.0.0.1 9050-9050
  3. Port 9050 - open
  4. That's all.

Co dalej? Może jakiś pomysł? - ten przykład był prosty, więc w następnym spróbujesz zrobić może skanowanie portów z użyciem tylko jednej flagi. Będzie to trochę taka kompilacja tego i poprzedniego arta.


Your browser doesn't support this tag cloud