Το Debian στην Ελλάδα

Top Menu

  • Αρχική
  • Forum
  • Blogs
  • Wiki
  • Επικοινωνία
Αρχική σελίδα

Μετατροπή ενός απλού tcp client σε port scanner

Submitted by kegior on Σαβ, 13/06/2009 - 01:54.
  • Προγραμματισμός

Λίγα λόγια για το tcpscan

Μπορείτε να το βρείτε εδώ.

Με το πρόγραμμα tcpscan μπορείτε να πραγματοποιήσετε tcp συνδέσεις με απομακρυσμένους υπολογιστές σε μία πόρτα που θα ορίσετε από τη γραμμή εντολών, καθώς τρέχετε το πρόγραμμα, πχ:  tcpscan Scylla.cs.uoi.gr 22
Το tcpscan για να συνδεθεί με τον απομακρυσμένο υπολογιστή χρησιμοποιεί υποδοχές (sockets), και την κλήση connect. Θα εξηγήσουμε τα βασικά του σημεία:

To αρχείο etc/protocol του  linux περιέχει πληροφορίες για τα διαθέσιμα πρωτόκολλα δικτύου. Εμείς το μόνο που έχουμε να κάνουμε είναι να ψάξουμε σε αυτό το αρχείο το αναγνωριστικό του πρωτοκόλλου tcp που θα χρησιμοποιήσουμε. Για να το πετύχουμε αυτό χρησιμοποιούμε τη συνάρτηση getprotobyname:

struct protoent *protocol;

protocol = getprotobyname( "tcp" );

 

Στη συνέχεια χτίζουμε τις υποδοχές με της οποίες θα γίνει η επικοινωνία με τη συνάρτηση socket:

int sd;
int rval; 
int port; 
sd = socket( PF_INET, SOCK_STREAM, protocol->p_proto );

Το sd είναι πλέον το αναγνωριστικό της υποδοχής μας.

Απομένει να συνδεθούμε με τον απομακρυσμένο υπολογιστή. Το linux και όλη οικογένεια λειτουργικών POSIX μας προσφέρει τη συνάρτηση:
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);                                          

  • sockfd: το αναγνωριστικό της υποδοχής που θα χρησιμοποιήσουμε
  • struct sockaddr:  Η διεύθυνση του απομακρυσμένου υπολογιστή. Εμείς θα χρησιμοποιήσουμε την sockaddr_in  struct διότι μας προσφέρει τη δυνατότητα εκτός από τη διεύθυνση να ορίσουμε και πόρτα επικοινωνίας.
  • addrlen: Το μήκος της διεύθυνσης.

memset( &socketaddr, 0, sizeof(socketaddr)); /* initialize it     */ 
socketaddr.sin_family = AF_INET; /* set the fam type to Internet */
socketaddr.sin_port = htons( port );  /* set port to argv[2]     */

Τώρα απομένει να χτίσουμε τη διεύθυνση του απομακρυσμένου υπολογιστή. Σε αυτό θα μας βοηθήσει η συνάρτηση struct hostent *gethostbyname(const char *name). Το όρισμά της μπορεί να είναι είτε μια διεύθυνση IP είτε ένα όνομα (hostname):

hostaddr = gethostbyname(argv[1]);
if ( !hostaddr )
{
fprintf( stderr, "gethostbyname(): %s\n", hstrerror(h_errno) );
return (h_errno);
}    
    
/* Now we'll use memcpy() to place it in our sockaddr_in struct: */
   
memcpy( &socketaddr.sin_addr, hostaddr->h_addr, hostaddr->h_length ); 
   
/* At this point, we're ready to connect to the remote host:     */

rval = connect( sd, (struct sockaddr *) &socketaddr, sizeof(socketaddr) );
if ( rval == -1 )
{
perror( "connect()" );
return (errno);
}

Πλέον έχουμε συνδεθεί επιτυχώς με το απομακρυσμένο σύστημα και μπορούμε να ανταλλάξουμε πληροφορίες. Αυτό το κομμάτι όμως δε θα μας απασχολήσει εδώ.

 

Μετατροπή σε port scanner

 

Είναι πολύ εύκολο να μετατρέψουμε το παραπάνω πρόγραμμα σε ένα port scanner. Aς δούμε πως:

Αφαιρούμε από το tcpconnect τις γραμμές κώδικα που υλοποιεί τη μεταβίβαση μηνυμάτων δηλαδή από τη γραμμή      printf("\nConnection with %s on port %d established!\n\a",argv[1],port); και κάτω.

Προσθέτουμε τις παρακάτω γραμμές σε ένα loop:

 

for (port=0;port<PORT_MAX;port++) {

if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,  sizeof tv))

{

perror("setsockopt");

return -1;

}

memset( &socketaddr, 0, sizeof(socketaddr)); /* initialize it     */ 

socketaddr.sin_family = AF_INET; /* set the fam type to Internet */

socketaddr.sin_port = htons( port );  /* set port to argv[2]     */

hostaddr = gethostbyname(argv[1]);

if ( !hostaddr )

{

fprintf( stderr, "gethostbyname(): %s\n", hstrerror(h_errno) );

return (h_errno);

}       

memcpy( &socketaddr.sin_addr, hostaddr->h_addr, hostaddr->h_length ); 

[code]rval = connect( sd, (struct sockaddr *) &socketaddr, sizeof(socketaddr) );

if ( rval == -1 )

{

perror( "connect()" );

return (errno);

}

close(sd);

}

Και κάτω από το if (rval == -1) προσθέτουμε τον εξής κώδικα:

else {
printf(“Found OPEN port: %d\n”,port);
}

Πλέον, ο port scanner μας είναι έτοιμος, αλλά έχει ένα μικρό προβληματάκι. Πολλές φορές η connect δε μπορεί να συνδεθεί κατευθείαν σε μία πόρτα, οπότε περιμένει ένα ακαθόριστο χρονικό διάστημα μέχρι να συνδεθεί η να απορριφθεί η αίτηση σύνδεσης. Το φαινόμενο αυτό κάνει τον port scanner μας αργό.

Για να αντιμετωπίσουμε το παραπάνω πρόβλημα χρησιμοποιούμε non_blocking socket, τη συνάρτηση select και δομή timeval:

#include <fcntl.h>
fd_set myset;
struct timeval tv;
socklen_t lon;
int valopt;
int lp,hp,ans;

Με την παρακάτω εντολή μετατρέπουμε την υποδοχή μας σε non-blocking:

fcntl(sd, F_SETFL, (flags = fcntl(sd,F_GETFL)) | O_NONBLOCK );

Αυτό σημαίνει ότι κάθε κλήση connect θα επιστρέφει -1 δηλαδή κωδικό λάθους. Το κλειδί εδώ είναι ότι ο κωδικός λάθους που θα επιστρέφεται σε περίπτωση timeout θα είναι γνωστός: EINPROGRESS

Οπότε το μόνο που πρέπει να κάνουμε είναι να ελέγξουμε αρχικά με μία if τον κωδικό λάθους. Αν αυτός είναι ο EINPROGRESS, τότε καθορίζουμε το χρόνο του timeout :

tv.tv_sec = TIMEOUT_TIME;
tv.tv_usec = 0;

Στη συνέχεια αρχικοποιούμε τον περιγραφέα myset που θα χρειαστούμε για τη select με τον περιγραφέα της υποδοχής μας:

FD_ZERO(&myset);
FD_SET(sd, &myset);

Έπειτα καλούμε τη select:

if (select(sd+1, NULL, &myset, NULL, &tv) > 0) {
lon = sizeof(int);
getsockopt(sd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
if (!valopt) {
printf("--- Found OPEN Port: %d\n",port);                  
} 
}
else {
printf("------ TIMEOUT on port: %d\n",port);     
}

Η select μας βοηθάει να προσδιορίσουμε μια συνθήκη λάθους για κάποιον από τους περιγραφείς μας.  Η σύνταξή της είναι η ακόλουθη:

 

#include <sys/time.h>

#include <sys/types.h>
#include <sys/select.h>

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

FD_SET(int fd, fd_set *fdset);
FD_CLR(int fd, fd_set *fdset);
FD_ISSET(int fd, fd_set *fdset);

FD_ZERO(fd_set *fdset);

Για περισσότερες πληροφορίες σχετικά με τη select ανατρέξτε εδώ

Κατεβάστε το ολοκληρωμένο TCPscan από εδώ

5
Average: 5 (4 votes)
Your rating: None
  • Login or register to post comments

Επιλογές

  • Τι είναι το Debian
    • Ιστορία του Debian
    • Εκδόσεις του Debian
    • Άδεια χρήσης
    • Χορηγίες
  • Κατεβάστε το Debian
  • Tutorials
  • Ελληνικά στο Debian
  • Νέα - Ειδήσεις
  • Debian FAQ
  • Εγχειρίδια
  • Συνεντεύξεις
  • #debian.gr στο IRC
  • Software Directory
  • Λίστα Ελλήνων Χρηστών debian
  • Image galleries

Πλοήγηση

  • Create content
    • Issue

Σύνδεση χρήστη

  • Δημιουργία νέου λογαριασμού
  • Αίτηση νέου κωδικού

New forum topics

  • MSN Messenger Clone
  • Offline εγκατάσταση πακέτων
  • Fosscom 2010 Θεσσαλονίκη
  • Port forward για torrent client;
  • Δε μπορώ να στείλω αρχεία με το bluetooth
  • πρόβλημα εγκατάστασης nvidia driver GTS250.
  • ρυθμιση pidgin για χρηση στο windows live
  • Rapidshare download
  • Offline instalation;
  • Segfault σε lib6 2.7
περισσότερα

Νέοι χρήστες

  • credswerway
  • crow
  • Lochecillssa
  • viagrarxcheap
  • alexandrosorodios

Online χρήστες

Προς το παρόν υπάρχουν 0 users και 4 guests online.

Disclaimer

This is not an official website of the Debian Project. It is located at www.debian.org.

Active forum topics

  • Fosscom 2010 Θεσσαλονίκη
  • MSN Messenger Clone
  • Offline εγκατάσταση πακέτων
  • Δε μπορώ να στείλω αρχεία με το bluetooth
  • Port forward για torrent client;
  • Rapidshare download
  • ρυθμιση pidgin για χρηση στο windows live
  • πρόβλημα εγκατάστασης nvidia driver GTS250.
  • Offline instalation;
  • Segfault σε lib6 2.7
περισσότερα

Recent comments

  • Δευτέρα 8
    gekaklam
    08/03/2010 - 21:05
  • MSN on Linux
    johnp
    07/03/2010 - 23:18
  • κοιτα σαν
    crow
    05/03/2010 - 13:51
  • προς το παρών
    bermi
    05/03/2010 - 12:11
περισσότερα

Οι πιο πρόσφατες καταχωρίσεις blog.

  • Ο κύκλος ενός πακέτου
  • 2010
  • TasPython.eu
  • Downtime
  • καλορίζικο!!!
  • "burn baby burn, mailist infernooooooo, burn baby burn.... <guitar solo>"
  • Set the record straight...
  • 1η Συνέλευση φίλων ΕΛ/ΛΑΚ Χανίων 24/1/09
  • Iceweasel search-plugin
  • λίγες σκέψεις και ευχαριστίες
περισσότερα
Ελληνική Κοινότητα Debian  |   Κοινότητα ΦΛΑΚ