Logo Search packages:      
Sourcecode: paketto version File versions  Download package

scanutil.c

#include <scanutil.h>
#include <d_services.h>

long bake_syncookie(u_char *ipp, u_char *key)
{
   u_char buf[MX_B];
   struct libnet_ip_hdr *ip = NULL;
   struct libnet_tcp_hdr *tcp = NULL;

   u_char syncookie[20];
   long synbits;
   
   (char *)ip  = (char *)ipp;
   (char *)tcp = (char *)ip + (int)ip->ip_hl*4;


    bzero(buf, sizeof(buf));
    memcpy(buf,   &ip->ip_src, 4);
    memcpy(buf+4, &ip->ip_dst, 4);
    memcpy(buf+8, &tcp->th_sport, 2);
    memcpy(buf+10,&tcp->th_dport, 2);
      
   pk_hmac(syncookie, key, buf, 12);
   memcpy(&synbits, &syncookie, sizeof(synbits));

   /*fprintf(stderr, "Sending: %lx vs. %lx from %i/%i\n", ntohl(synbits), 0,
      ntohs(tcp->th_sport), ntohs(tcp->th_dport));*/

   return(synbits);
}

long munch_syncookie(u_char *ipp, u_char *key)
{
   u_char buf[MX_B];
   struct libnet_ip_hdr *ip = NULL;
   struct libnet_tcp_hdr *tcp = NULL;
   int i = 1;

   u_char syncookie[20];
   long synbits;

   (char *)ip  = (char *)ipp;
   (char *)tcp = (char *)ip + (int)ip->ip_hl*4;

   bzero(buf, sizeof(buf));
   memcpy(buf,   &ip->ip_dst, 4);   
   memcpy(buf+4, &ip->ip_src, 4);   
   memcpy(buf+8, &tcp->th_dport, 2);
   memcpy(buf+10,&tcp->th_sport, 2);

   pk_hmac(syncookie, key, buf, 12);

   memcpy(&synbits, &syncookie, sizeof(synbits));

   if(tcp->th_flags == TH_RST) /* Distco st00 rides again */
   {
      if(!(ntohl(tcp->th_ack))) tcp->th_ack = tcp->th_seq; /* WEIRD fix */
      i=0;/* RST's don't increment */
   }

   if(ntohl(tcp->th_ack)-i == ntohl(synbits))
   {
      return(synbits);
   }

   else{
      return(0); // this screws up 1/2^32 times.
   }
}

/* XXX shaddup shaddup i know raw_sock_syn_scan is horrifying, shaddup */

int raw_sock_syn_scan(char *dest, int length, char *dev, struct frame *scanx,
                      char *ttlrange, char *seed, char *bandwidth, int verbose, int resolve,
                      int disable_seq)
{
   char abuf[1024], bbuf[1024], cbuf[1024], dbuf[1024], pbuf[1024], tbuf[1024], rbuf[1024];
   unsigned short a, b, c, d, ttl, start_a, end_a, start_b, end_b;
   unsigned short start_c, end_c, start_d, end_d, start_p, end_p;
   unsigned short start_ttl, end_ttl;
   unsigned int dport;

   unsigned int base, multiple, packetsleep;
   int knownscan = 0;
   int kcount = 0;
   int flag = 0;
      
   struct timeval now, then, bench_pre, bench_post, diff;

   struct libnet_link_int *temp = NULL;
   int sockfd = -1;
   int i,j,source_port = ntohs(scanx->tcp->th_sport);
   int keep_ipid = 0;
   char buf[MX_B], buf2[MX_B];

   struct in_addr temp_ip;
   struct libnet_plist_chain *alist, *blist, *clist, *dlist, *plist, *tlist;
  
   sockfd = libnet_open_raw_sock(IPPROTO_RAW);

   gettimeofday(&then, NULL);
   
   if(!sockfd)
   {
      fprintf(stderr, "Couldn't open raw socket.\n");
      exit(1);
   }

   /* We need to figure out how fast we're allowed to send packets.  We do this
    * by noting that our standard packet is 40 bytes, plus 14 from ethernet, yielding
    * 54 bytes on the wire.  Ah, but the minimum size for an ethernet frame is 64 bytes,
    * and until I get off my duff and properly support non-ether interfaces, that'll
    * have to be our per-packet cost.  
    */


   if(!bandwidth || bandwidth[0]=='0') packetsleep=0;
   else{
      i=sscanf(bandwidth, "%1024[^BbKkMmGg]%1024s", buf, buf2);
      if(i==0)return(0);
      base=atoi(buf);
      if(i==1){buf2[0]='B'; i=2;}
      if(i==2)switch(buf2[0]){
            case 'B':
                  multiple=1;
                  break;
            case 'b':
                  multiple=1;
                  break;
            case 'K':
                  multiple=1024;
                  break;
            case 'k':
                  multiple=1024;
                  break;
            case 'M':
                  multiple=1024*1024;
                  break;
            case 'm':
                  multiple=1024*1024;
                  break;
            case 'G':
                  multiple=1024*1024*1024;
                  break;
            case 'g':
                  multiple=1024*1024*1024;
                  break;
            }           
      i=base*multiple;
     /* XXX Need to incorporate time spent actually sending packets :-) */
      packetsleep=(1000000*64)/i; /* 64 is minimum frame size */
   }        
   if(sscanf(dest, "%1024[^.].%1024[^.].%1024[^.].%1024[^:]:%1024[^/]%1024s",
        abuf, bbuf, cbuf, dbuf, pbuf, rbuf) != 6) return(0);

   if(!ttlrange){
      ttlrange = malloc(1024);
      snprintf(ttlrange, 1024, "%i-%i", scanx->ip->ip_ttl, scanx->ip->ip_ttl);
  }
   if(!strncmp(pbuf, "known", sizeof(pbuf))){
         knownscan++;
         snprintf(pbuf, sizeof(pbuf), "0-1");
   }

   libnet_plist_chain_new(&alist, abuf);
   while(libnet_plist_chain_next_pair(alist, &start_a, &end_a)){
    libnet_plist_chain_new(&blist, bbuf);
    while(libnet_plist_chain_next_pair(blist, &start_b, &end_b)){
     libnet_plist_chain_new(&clist, cbuf);
     while(libnet_plist_chain_next_pair(clist, &start_c, &end_c)){
      libnet_plist_chain_new(&dlist, dbuf);
      while(libnet_plist_chain_next_pair(dlist, &start_d, &end_d)){
       libnet_plist_chain_new(&plist, pbuf);
       while(libnet_plist_chain_next_pair(plist, &start_p, &end_p)){
         libnet_plist_chain_new(&tlist, ttlrange);
         while(libnet_plist_chain_next_pair(tlist, &start_ttl, &end_ttl)){
          /* libnet_plist was meant for port lists, but we're hacking it
             to do IP/TTL lists as well.  Though an IP is 32 bytes, ports are
             16 bytes, and each range is an 8 byte range.  So, we clamp the
             iteration to an 8 byte range. */
          if(start_a > 255) start_a = 255;     if(end_a > 255) end_a = 255;
          if(start_b > 255) start_b = 255;     if(end_b > 255) end_b = 255;
          if(start_c > 255) start_c = 255;     if(end_c > 255) end_c = 255;
          if(start_d > 255) start_d = 255;     if(end_d > 255) end_d = 255;
          if(start_ttl > 255) start_ttl = 255; if(end_ttl > 255) end_ttl = 255;
                   
          //fprintf(stderr, "%u-%u.%u-%u.%u-%u.%u-%u:%u-%u\n", start_a, end_a, start_b,
         //    end_b, start_c, end_c, start_d, end_d, start_p, end_p);

          
          for(ttl=start_ttl; ttl<=end_ttl; ttl++){
          for(a=start_a; a<=end_a; a++){
          for(b=start_b; b<=end_b; b++){
          for(c=start_c; c<=end_c; c++){ 
             //usleep(subnet_sleep*1000);
             gettimeofday(&now, NULL);
          for(d=start_d; d<=end_d && d; d++){
          for(dport=start_p; dport<=end_p; dport++){ 

           scanx->ip->ip_dst.s_addr = ntohl(a*256*256*256 + b*256*256 + c*256 + d);
             /*bzero(buf, sizeof(buf));
             snprintf(buf, sizeof(buf), "%u.%u.%u.%u", a, b, c, d);
             inet_aton(buf, &scanx->ip->ip_dst);*/ /* cheap trick */
           if(!disable_seq){
                   scanx->tcp->th_dport = htons(dport);
                 scanx->tcp->th_sport = htons(source_port - 255 + ttl ); /* XXX i know, i know -- this needs to be time */
                 }
             if(knownscan){
                 scanx->tcp->th_dport = htons(knownports[kcount].port);
                 if(kcount<1150)dport=0;
                 else           dport=1;
                 kcount++;
           }
           scanx->ip->ip_ttl = ttl;
             scanx->ip->ip_id =  htons(ttl); /* redundant hop capacity, for your convenience */
            
             if(!disable_seq){
                   i=bake_syncookie((u_char *)scanx->ip, seed);
                   memcpy(&scanx->tcp->th_seq, &i, 4);
                 if(scanx->tcp->th_flags == TH_ACK){
                 memcpy(&scanx->tcp->th_ack, &i, 4);
                 }
           }
          
             recalc_checksums(scanx, scanx->ip->ip_p);
             i = libnet_write_ip(sockfd, (char *)scanx->ip, (int)scanx->ip->ip_hl*4 + (int)scanx->tcp->th_off*4);
             if(verbose>=1){
                     gettimeofday(&now, NULL);
                     timeval_subtract(&diff, &now, &then);
               fprintf(stdout, "%s: %16.16s:%-5i [%2.2hu]", "SENT", inet_ntoa(scanx->ip->ip_dst), ntohs(scanx->tcp->th_dport), 0);
               fprintf(stdout, "%4lu.%3.3lus", diff.tv_sec, diff.tv_usec/1000);
               if(resolve)fprintf(stdout, "(%35.35s)\n", libnet_host_lookup(scanx->ip->ip_dst.s_addr, 1));
               else       fprintf(stdout, "\n"); /*fprintf(stdout, "(%29.29s)\n", buf); */
            }
             if(verbose>=2){
                  fprintf(stderr, "Sent %i on %s:\n", i, dev);
                  fprintf(stderr, " "); print_ip((char *)scanx->ip);
            fprintf(stderr, " "); print_tcp((char *)scanx->tcp, 0);
            }
           if(packetsleep)usleep(packetsleep);
          }}}}}} /* all those for loops */
         }libnet_plist_chain_free(tlist);
        } libnet_plist_chain_free(plist);
       }  libnet_plist_chain_free(dlist);
      }   libnet_plist_chain_free(clist); 
     }    libnet_plist_chain_free(blist);
    }     libnet_plist_chain_free(alist);
    return(0);
}

struct frame *build_generic_syn(struct frame *x)
{
   x->data = malloc(2048);

   x->eth = x->data;
   
   libnet_build_ethernet("000000",     /*x.eth->ether_dhost*/
                         "000000",  /*x.eth->ether_shost*/
                         ETHERTYPE_IP, /*x.eth->ether_type*/
                         NULL,          /*extra crap to tack on*/
                         0,             /*how much crap*/
                         (char *)x->eth);
 
   (char *)x->ip = (char *)x->eth + LIBNET_ETH_H;
   
   libnet_build_ip(LIBNET_TCP_H,
                0, // tos
                1234, // ipid
                0,    // frag
                255,  // ttl
                IPPROTO_TCP,
                0, //source
                0, // dest
                NULL, // ip payload
                0,    // ip payload size
                (char *)x->ip);
   
   x->ip->ip_off = 64; /* set DF flag */
   (char *)x->tcp = (char *)x->ip + (int)x->ip->ip_hl*4;
   
   libnet_build_tcp(12345, // source port
                 139,  // dest port
                 420, // seq
                 0, // ack
                 TH_SYN, // flags
                 4096, // win
                 0, // urgp
                 NULL, // tcp payload
                 0, // tcp payload size
                 (char *)x->tcp);
   return(x);
}

int estimate_hopcount(int ttl)
{
   /* tip of the hat to nomad's despoof -- no, this ain't supposed to be perfect */
   int passive_factor=32; /* may be low but i found a host w/ base TTL 32 */
              /* i've heard rumors of hosts w/ ttl base 240 but
                 haven't found any yet */
              /* when wrong, it'll usually be off by 4 (damn 60 ttl hosts)*/
   int distco_factor = 216; /* any less and we hit win32 ttl=128, any more and valid */
   if(ttl < (distco_factor-80) || ttl > distco_factor) /* handles up to 40 hops */
   {
      if(ttl%passive_factor == 0)ttl--; 
      return(passive_factor - (ttl%passive_factor));   
   } else {
      return((distco_factor - ttl + 1) / 2); /* they don't adjust ttl when they RST! */
   }
}

int parse_dest(char *dest, int length, char *shortdest, int multi)
{
       char buf[MX_B], buf2[MX_B], destbuf[1024], rangebuf[1024], portbuf[1024];
       int i,j,k,l;
       struct in_addr temp_ip;
       const char quickbuf[] = "80,443,445,53,20-23,25,135,139,8080,110,111,143,1025,5000,465,993,31337,79,8010,8000,6667,2049,3306";
       const char squickbuf[] = "80,443,139,21,22,23";

       
       /* there's gotta be an easier way to do this :-)
        * basically we're splitting the destination string into
        * destination, CIDR range, and ports...the whole purpose of
        * this function is to take whatever garbage the user gave us
        * and convert it to my canonical form -- or die trying.
        */
       sscanf(shortdest, "%1024[^/]/%1024s", buf, rangebuf); /* only need range */
       sscanf(shortdest, "%1024[^:/]:%1024[^:/]:%1024s", destbuf, portbuf, buf);

       if(!destbuf[0]){
       return(0);
       }

     /* So, here's the deal.  By default, I want to scan the bejesus out of a single host, but
        I don't want to throw out thousands of packets per host for a simple
        traceroute or netsweep.  So there's differential default behavior, but it's doing
        the Right Thing.  Manual override of course can do anything. */
        
       i=0;
       k=0;

       while(i<1024 && destbuf[i]!=0){
          if((destbuf[i]=='-' || destbuf[i]==',')){
                k=2; /* might be plural */
          }
          else if((destbuf[i]>='A' && destbuf[i]<='Z') ||
                  (destbuf[i]>='a' && destbuf[i]<='z')){
            j++;
          }
          if(destbuf[i]=='\n' || destbuf[i] == '\r'){
              destbuf[i]=0; /* chomp, DNS resolver needs no trailing newline */
            }
          i++;
       }
       
      if(k==2 && !j) multi=2;/* found dash/comma w/o DNS -- must be multi */
      if(j){ /* found ASCII character */
              temp_ip.s_addr = libnet_name_resolve(destbuf, 1);
            if(!memcmp(&temp_ip.s_addr, "\xff\xff\xff\xff", IPV4_ADDR_LEN)){
                  //fprintf(stderr, "Couldn't resolve name: %s\n", destbuf);
                  return(0);
            } else  snprintf(destbuf, 1024, "%s", inet_ntoa(temp_ip));
      }

       if(sscanf(destbuf, "%1024[^.].%1024[^.].%1024[^.].%1024s", buf,buf,buf,buf) != 4){
              fprintf(stderr, "Invalid IP Specification:  Not enough octets(four needed).\n");
              return(0);
       }

       if(!atoi(rangebuf) || atoi(rangebuf)>32 || j+k==2) snprintf(rangebuf, sizeof(rangebuf), "32");
       if(atoi(rangebuf) < 32) multi=3;
                         
       if(!portbuf[0]){  /* no default ports?  Whatever shall we do! */
            if(multi) snprintf(portbuf, sizeof(portbuf), "80");
            else      snprintf(portbuf, sizeof(portbuf), "quick"); /* was d */
       }
       /* ok lets set up some defaults */
       if(!strncmp(portbuf, "quick", sizeof(portbuf))){
          snprintf(portbuf, sizeof(portbuf), "%s", quickbuf);
       }
       if(!strncmp(portbuf, "squick", sizeof(portbuf))){
        snprintf(portbuf, sizeof(portbuf), "%s", squickbuf);
       }
       if(!strncmp(portbuf, "all", sizeof(portbuf))){
        snprintf(portbuf, sizeof(portbuf), "0-65535");
       }
       /* we set up knownscan in raw_sock itself */
       
       snprintf(dest, length, "%s:%s/%s", destbuf, portbuf, rangebuf);
       return(1);
}

Generated by  Doxygen 1.6.0   Back to index