[My Home Page] [Contact information] [My Bookmark] [Music Page] [Articles] [HackPage] [Sign Guestbook] [My Public PGP Key]

Russian LinkExchange Advertising Network
Russian LinkExchange Member

Приложение 4. Программа сканирования TCP портов.

/*
 * resolve.c
 *           by Uriel Maimon (lifesux@cox.org)
 */
#include 
#include 
#include 
#include 
#include 

int resolve( const char *name, struct sockaddr_in *addr, int port )
     {
        struct hostent *host;

        /* clear everything in case I forget something */
        bzero(addr,sizeof(struct sockaddr_in));

        if (( host = gethostbyname(name) ) == NULL )  {
#ifndef RESOLVE_QUIET
           fprintf(stderr,"unable to resolve host \"%s\" -- ",name);
           perror("");
#endif
           return -1;
        }

        addr->sin_family = host->h_addrtype;
        memcpy((caddr_t)&addr->sin_addr,host->h_addr,host->h_length);
        addr->sin_port = htons(port);

        return 0;
     }

int resolve_rns( char *name , unsigned long addr )
     {
        struct hostent *host;
        unsigned long address;

        address = addr;
        host = gethostbyaddr((char *)&address,4,AF_INET);

        if (!host)  {
#ifndef RESOLVE_QUIET
           fprintf(stderr,"unable to resolve host \"%s\" -- ",inet_ntoa(addr));
           perror("");
#endif
           return -1;
        }
        strcpy(name,host->h_name);
        return 0;
     }

unsigned long addr_to_ulong(struct sockaddr_in *addr)
     {
        return addr->sin_addr.s_addr;
     }
/*
 * EOF
 *//*
 * tcp_pkt.c
 *           by Uriel Maimon (lifesux@cox.org)
 */

/* remove inlines for smaller size but lower speed */
#include 
#include 
#include 
#include 
#include 

#define IPHDRSIZE sizeof(struct iphdr)
#define TCPHDRSIZE sizeof(struct tcphdr)
#define PSEUDOHDRSIZE sizeof(struct pseudohdr)

    /*
     * in_cksum --
     *  Checksum routine for Internet Protocol family headers (C Version)
     */
unsigned short in_cksum(addr, len)
    u_short *addr;
    int len;
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 0;

    /*
     * Our algorithm is simple, using a 32 bit accumulator (sum), we add
     * sequential 16 bit words to it, and at the end, fold back all the
     * carry bits from the top 16 bits into the lower 16 bits.
     */
    while (nleft > 1)  {
        sum += *w++;
        nleft -= 2;
    }

    /* mop up an odd byte, if necessary */
    if (nleft == 1) {
        *(u_char *)(&answer) = *(u_char *)w ;
        sum += answer;
    }

    /* add back carry outs from top 16 bits to low 16 bits */
    sum = (sum >> 16) + (sum & 0xffff);   /* add hi 16 to low 16 */
    sum += (sum >> 16);                   /* add carry */
    answer = ~sum;                        /* truncate to 16 bits */
    return(answer);
}

     /*
      * HEXDUMP()
      *
      * not too much to explain
      */
inline void HEXDUMP(unsigned len, unsigned char *data)
{
   unsigned i;
   for (i=0;isaddr = s_addr;
        pseudo->daddr = t_addr;
        pseudo->protocol = IPPROTO_TCP;
        pseudo->tcplength = htons(TCPHDRSIZE+datasize);

        /* The TCP pseudo-header was created. */

        tcp->th_sport   = htons(s_port);
        tcp->th_dport   = htons(t_port);
        tcp->th_off     = 5;          /* 20 bytes, (no options) */
        tcp->th_flags   = tcpflags;
        tcp->th_seq     = htonl(seq);
        tcp->th_ack     = htonl(ack);
        tcp->th_win     = htons(win); /* we don't need any bigger, I guess. */

        /* The necessary TCP header fields are set. */

        tcp->th_sum = in_cksum(pseudo,PSEUDOHDRSIZE+TCPHDRSIZE+datasize);

        memset(packet,0,IPHDRSIZE);
        /* The pseudo-header is wiped to clear the IP header fields */

        ip->saddr    = s_addr;
        ip->daddr    = t_addr;
        ip->version  = 4;
        ip->ihl      = 5;
        ip->ttl      = 255;
        ip->id       = random()%1996;
        ip->protocol = IPPROTO_TCP; /* should be 6 */
        ip->tot_len  = htons(IPHDRSIZE + TCPHDRSIZE + datasize);
        ip->check    = in_cksum((char *)packet,IPHDRSIZE);

        /* The IP header is intact. The packet is ready. */

#ifdef TCP_PKT_DEBUG
        printf("Packet ready. Dump: \n");
#ifdef TCP_PKT_DEBUG_DATA
        HEXDUMP(IPHDRSIZE+TCPHDRSIZE+datasize,packet);
#else
        HEXDUMP(IPHDRSIZE+TCPHDRSIZE,packet);
#endif
        printf("\n");
#endif

        return sendto(socket, packet, IPHDRSIZE+TCPHDRSIZE+datasize, 0, (struct sockaddr *)address, sizeof(struct sockaddr));
     }
/*
 * EOF
 */
/*
 *  Port Scanning without the SYN flag / Uriel Maimon
 *  (lifesux@cox.org)
 */

#define RESOLVE_QUIET

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "resolve.c"
#include "tcp_pkt.c"

#define STCP_VERSION "1.32"
#define STCP_PORT  1234                /* Our local port. */
#define STCP_SENDS 3
#define STCP_THRESHOLD 8
#define STCP_SLOWFACTOR 10

void banner(void)
     {
        printf("\nscantcp\n");
        printf("version %s\n",STCP_VERSION);
     }

void usage(const char *progname)
     {
        printf("\nusage: \n");
        printf("%s       [sf]\n\n",progname);
        printf("\t : 0: half-open scanning (type 0, SYN)\n");
        printf("\t           1: stealth scanning (type 1, FIN)\n");
        printf("\t           2: stealth scanning (type 2, ACK)\n");
        printf("\t : source address (this host)\n");
        printf("\t   : target to scan\n");
        printf("\t  : ports/and or ranges to scan - eg: 21-30,113,6000\n");
        printf("\t : microseconds to wait between TCP sends\n");
        printf("\t  : seconds to wait for TCP replies\n");
        printf("\t[sf]     : slow-factor in case sends are dectected to be too fast\n\n");
     }

unsigned char *dest_name;
unsigned char *spoof_name;
struct sockaddr_in destaddr;
unsigned long dest_addr;
unsigned long spoof_addr;
unsigned long usecdelay;
unsigned      waitdelay;

int slowfactor = STCP_SLOWFACTOR;

struct portrec                         /* the port-data structure */
{
   unsigned           n;
   int                state;
   unsigned char      ttl;
   unsigned short int window;
   unsigned long int  seq;
   char               sends;
} *ports;

char *portstr;
unsigned char scanflags;
int done;
int rawsock;                           /* socket descriptors */
int tcpsock;
int lastidx = 0;                       /* last sent index */
int maxports;                          /* total number of ports */

void timeout(int signum)               /* timeout handler           */
     {                                 /* this is actually the data */
        int someopen = 0;              /* analyzer function. werd.  */
        unsigned lastsent;
        int checklowttl = 0;

        struct portrec *p;

        printf("* SCANNING IS OVER\n\n");
        fflush(stdout);

        done = 1;

        for (lastsent = 0;lastsentstate == -1)
               if (p->ttl > 64)
               {
                  checklowttl = 1;
                  break;
               }
          }

/* the above loop checks whether there's need to report low-ttl packets */

        for (lastsent = 0;lastsentn);

             tcpip_send(rawsock,&destaddr,
                        spoof_addr,destaddr.sin_addr.s_addr,
                        STCP_PORT,ntohs(destaddr.sin_port),
                        TH_RST,
                        p->seq++, 0,
                        512,
                        NULL,
                        0);
          }                            /* just RST -everything- sent   */
                                       /* this inclued packets a reply */
                                       /* (even RST) was recieved for  */
        for (lastsent = 0;lastsentstate)
                    {
                     case -1: break;
                     case 1 : printf("# port %d is listening.\n",p->n);
                       someopen++;
                       break;
                     case 2 : printf("# port %d maybe listening (unknown response).\n",
                                     p->n);
                       someopen++;
                       break;
                     default: printf("# port %d needs to be rescanned.\n",p->n);
                    }
                  break;
                case TH_ACK:
                  switch (p->state)
                    {
                     case -1:
                       if (((p->ttl < 65) && checklowttl) || (p->window >0))
                         {
                            printf("# port %d maybe listening",p->n);
                            if (p->ttl < 65) printf(" (low ttl)");
                            if (p->window >0) printf(" (big window)");
                            printf(".\n");
                            someopen++;
                         }
                       break;
                     case 1:
                     case 2:
                       printf("# port %d has an unexpected response.\n",
                              p->n);
                       break;
                     default:
                       printf("# port %d needs to be rescanned.\n",p->n);
                    }
                  break;
                case TH_FIN:
                  switch (p->state)
                    {
                     case -1: break;
                     case 0 :
                       printf("# port %d maybe open.\n",p->n);
                       someopen++;
                       break;
                     default:
                       printf("# port %d has an unexpected response.\n",p->n);
                    }
               }
          }

        printf("-----------------------------------------------\n");
        printf("# total ports open or maybe open: %d\n\n",someopen);
        free(ports);

        exit(0);                       /* heh. */

     }

int resolve_one(const char *name, unsigned long *addr, const char *desc)
     {
        struct sockaddr_in tempaddr;
        if (resolve(name, &tempaddr,0) == -1) {
           printf("error: can't resolve the %s.\n",desc);
           return -1;
        }

        *addr = tempaddr.sin_addr.s_addr;
        return 0;
     }

void give_info(void)
     {
        printf("# response address           : %s (%s)\n",spoof_name,inet_ntoa(spoof_addr));
        printf("# target address             : %s (%s)\n",dest_name,inet_ntoa(dest_addr));
        printf("# ports                      : %s\n",portstr);
        printf("# (total number of ports)    : %d\n",maxports);
        printf("# delay between sends        : %lu microseconds\n",usecdelay);
        printf("# delay                      : %u seconds\n",waitdelay);
        printf("# flood dectection threshold : %d unanswered sends\n",STCP_THRESHOLD);
        printf("# slow factor                : %d\n",slowfactor);
        printf("# max sends per port         : %d\n\n",STCP_SENDS);
     }

int parse_args(int argc, char *argv[])
{
   if (strrchr(argv[0],'/') != NULL)
     argv[0] = strrchr(argv[0],'/') + 1;

   if (argc < 7)
   {
      printf("%s: not enough arguments\n",argv[0]);
      return -1;
   }

   switch (atoi(argv[1]))
   {
      case 0  : scanflags = TH_SYN; break;
      case 1  : scanflags = TH_FIN; break;
      case 2  : scanflags = TH_ACK; break;
      default : printf("%s: unknown scanning method\n",argv[0]);
                return -1;
   }
   spoof_name = argv[2];
   dest_name = argv[3];
   portstr = argv[4];
   usecdelay = atol(argv[5]);
   waitdelay = atoi(argv[6]);
   if (argc > 7) slowfactor = atoi(argv[7]);
   if ((usecdelay == 0) && (slowfactor > 0))
     {
        printf("%s: adjusting microsecond-delay to 1usec.\n");
        usecdelay++;
     }
   return 0;
}

int build_ports(char *str)       /* build the initial port-database */
{
   int i;
   int n;
   struct portrec *p;
   int sport;
   char *s;
   s        = str;
   maxports = 0;
   n        = 0;

   while (*s != '\0')
     {
        switch (*s)
          {
           case '0':
           case '1':
           case '2':
           case '3':
           case '4':
           case '5':
           case '6':
           case '7':
           case '8':
           case '9':
             n *= 10;
             n += (*s - '0');
             break;
           case '-':
             if (n == 0) return -1;
             sport = n;
             n = 0;
             break;
           case ',':
             if (n == 0) return -1;
             if (sport != 0)
               {
                  if (sport >= n) return -1;
                  maxports += n-sport;
                  sport = 0;
               } else
               maxports++;
             n = 0;
             break;
          }
        s++;
     }
   if (n == 0) return -1;
   if (sport != 0)
     {
        if (sport >= n) return -1;
        maxports += n-sport;
        sport = 0;
     }
   else
     maxports++;

   maxports+=2;

   if ((ports = (struct portrec *)malloc((maxports)*sizeof(struct portrec))) == NULL)
     {
        fprintf(stderr,"\nerror: not enough memory for port database\n\n");
        exit(1);
     }
   s        = str;
   maxports = 0;
   n        = 0;

   while (*s != '\0')
     {
        switch (*s)
          {
           case '0':
           case '1':
           case '2':
           case '3':
           case '4':
           case '5':
           case '6':
           case '7':
           case '8':
           case '9':
             n *= 10;
             n += (*s - '0');
             break;
           case '-':
             if (n == 0) return -1;
             sport = n;
             n = 0;
             break;
           case ',':
             if (n == 0) return -1;
             if (sport != 0)
               {
                  if (sport >= n) return -1;
                  while (sport <= n)
                    {
                       for (i=0;in == sport) break;

                       if (i < maxports-1 )
                         printf("notice: duplicate port - %d\n",sport);
                       else
                         {
                            (ports+maxports)->n = sport;
                            maxports++;
                         }
                       sport++;
                    }
                  sport = 0;
               } else
               {
                  for (i=0;in == n) break;

                  if (i < maxports-1 )
                    printf("notice: duplicate port - %d\n",n);
                  else
                    {
                       (ports+maxports)->n = n;
                       maxports++;
                    }
               }
             n = 0;
             break;
          }
        s++;
     }

   if (n == 0) return -1;
   if (sport != 0)
     {
        if (sport >= n) return -1;
        while (sport <= n)
          {
             for (i=0;in == sport) break;

             if (i < maxports-1 )
               printf("notice: duplicate port - %d\n",sport);
             else
               {
                  (ports+maxports)->n = sport;
                  maxports++;
               }
             sport++;
          }
        sport = 0;
     } else
     {
        for (i=0;in == n) break;

        if (i < maxports-1 )
          printf("notice: duplicate port - %d\n",n);
        else
          {
             (ports+maxports)->n = n;
             maxports++;
          }
     }

   printf("\n");

   for (i=0;istate = 0;
        p->sends = 0;
     }

   return 0;
}

struct portrec *portbynum(int num)
{
   int i = 0;
   while ( ((ports+i)->n != num) && (istate != 0) || (p->sends == STCP_SENDS))
          {
             doneports++;
             lastidx++;
             lastidx %= maxports;
          }
        else
          break;
     }

   if (save)
     lastidx = oldlastidx;
   else
     lastidx = (lastidx + 1) % maxports;

   if (doneports == maxports) return NULL;

   return p;
}

inline unsigned long usecdiff(struct timeval *a, struct timeval *b)
{
   unsigned long s;

   s = b->tv_sec - a->tv_sec;
   s *= 1000000;
   s += b->tv_usec - a->tv_usec;

   return s;                           /* return the stupid microsecond diff */
}

void main(int argc, char *argv[])
{
   int lastsent = 0;
    char buf[3000];
    struct iphdr  *ip   = (struct iphdr *)(buf);
   struct tcphdr *tcp  = (struct tcphdr *)(buf+sizeof(struct iphdr));
    struct sockaddr_in from;
   int fromlen;
    struct portrec *readport;
    fd_set rset, wset;
    struct timeval waitsend, now, del;
    unsigned long udiff;
    int sendthreshold = 0;

   banner();

   if (parse_args(argc,argv))
     {
        usage(argv[0]);
        return;
     }

   if (resolve_one(dest_name,
                    &dest_addr,
                    "destination host")) exit(1);

   destaddr.sin_addr.s_addr = dest_addr;
   destaddr.sin_family = AF_INET;

   if (resolve_one(spoof_name, &spoof_addr, "source host")) exit(1);

   if ( build_ports(portstr) == -1)
     {
        printf("\n%s: bad port string\n",argv[0]);
        usage(argv[0]);
        return;
     }

   give_info();

   if ((tcpsock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
     {
        printf("\nerror: couldn't get TCP raw socket\n\n");
        exit(1);
     }
   if ((rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
     {
        printf("\nerror: couldn't get raw socket\n\n");
        exit(1);
     }

   /* well, let's get to it. */

   done = 0;

   printf("* BEGINNING SCAN\n");
   fflush(stdout);

   gettimeofday(&waitsend,NULL);

   while (!done)
     {
        if (nextport(1) == NULL)
          {
             alarm(0);             /* no more sends, now we just  */
             signal(SIGALRM,timeout); /* to wait  seconds */
             alarm(waitdelay);        /* before resetting and giving */
          }                           /* results.                    */

        FD_ZERO(&rset);
        FD_SET(tcpsock,&rset);

        gettimeofday(&now,NULL);

        udiff = usecdiff(&waitsend,&now);

        /* here comes the multiple choice select().
         * well, there are 3 states:
         * 1. already sent all the packets.
         * 2. didn't send all the packets, but it's not time for another send
         * 3. didn't send all the packets and it is time for another send.
         */

        if (nextport(1) != NULL)
          if (udiff > usecdelay)
          {
             FD_ZERO(&wset);
             FD_SET(rawsock,&wset);
             select(FD_SETSIZE,&rset,&wset,NULL,NULL);
          } else
          {
             del.tv_sec = 0;
             del.tv_usec = usecdelay;
             select(FD_SETSIZE,&rset,NULL,NULL,&del);
          }
        else
          select(FD_SETSIZE,&rset,NULL,NULL,NULL);

        if (FD_ISSET(tcpsock,&rset))   /* process the reply */
          {
             fromlen = sizeof(from);

             recvfrom(tcpsock,&buf,3000,0,
                      (struct sockaddr *)&from,&fromlen);

             if (from.sin_addr.s_addr == destaddr.sin_addr.s_addr)
               if (ntohs(tcp->th_dport) == STCP_PORT)
               {
                  printf("* got reply");

                  readport = portbynum(ntohs(tcp->th_sport));

                  if (readport == NULL)
                    printf(" -- bad port");
                  else
                    {
                       sendthreshold = 0;
                       if (!readport->state)
                         {
                            readport->ttl    = ip->ttl;
                            readport->window = tcp->th_win;

                            if (tcp->th_flags & TH_RST)
                              {
                                 readport->state = -1;
                                 printf(" (RST)");
                                 if (readport->ttl    < 65) printf(" (short ttl)");
                                 if (readport->window > 0) printf(" (big window)");
                              }
                            else
                              if (tcp->th_flags & (TH_ACK | TH_SYN))
                              {
                                 readport->state = 1;
                                 printf(" (SYN+ACK)");
                                 tcpip_send(rawsock,&destaddr,
                                            spoof_addr,destaddr.sin_addr.s_addr,
                                            STCP_PORT,readport->n,
                                            TH_RST,
                                            readport->seq++, 0,
                                            512,
                                            NULL,
                                            0);
                              }
                            else
                              {
                                 readport->state = 2;
                                 printf(" (UNEXPECTED)");
                                 tcpip_send(rawsock,&destaddr,
                                            spoof_addr,destaddr.sin_addr.s_addr,
                                            STCP_PORT,readport->n,
                                            TH_RST,
                                            readport->seq++, 0,
                                            512,
                                            NULL,
                                            0);
                              }
                         }
                       else
                         printf(" (duplicate)");
                    }
                  printf("\n");
                  fflush(stdout);
               }
          }

        if (nextport(1) != NULL)
          if (FD_ISSET(rawsock,&wset)) /* process the sends */
          {
             readport = nextport(0);

             destaddr.sin_port = htons(readport->n);

             printf("* sending to port %d ",ntohs(destaddr.sin_port));

             readport->seq = lrand48();
             readport->sends++;

             tcpip_send(rawsock,&destaddr,
                        spoof_addr,destaddr.sin_addr.s_addr,
                        STCP_PORT,ntohs(destaddr.sin_port),
                        scanflags, readport->seq++, lrand48(),
                        512, NULL, 0);

             gettimeofday(&waitsend,NULL);

             FD_ZERO(&wset);
             printf("\n");

             if ((++sendthreshold > STCP_THRESHOLD) && (slowfactor))
               {
                  printf("\n\n -- THRESHOLD CROSSED - SLOWING UP SENDS\n\n");
                  usecdelay *= slowfactor;
                  sendthreshold = 0;
               }
          }
     }
}
/*
 * EOF
 */---

<== Back to main page counter
My Home Page How to contact me My Bookmarks Music Page Articles Hack Page Welcome to Guestbook Windows (1251) encoding Unix  (Koi8) encoding My Public PGP Key
Hosted by uCoz