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

paratrace.c

#include "paketto.h"
#include "pk_crypt.h"
#include "scanutil.h"
/*#include "d_services.h"*/

void paratrace_usage();

int main(int argc, char **argv)
{
   int opt;
   extern char *optarg;
   extern int   opterr; 

   pcap_t *pcap;        /* PCAP descriptor */
   u_char *packet;            /* Our newly captured packet */
   char pfprogram[2048];
   char dev[255];
   char *p;
   char target[1024];
   long source_ip  = 0;
   int source_port = 0;
   struct pcap_pkthdr pkthdr; /* PCAP packet information structure */
   struct bpf_program fp;     /* Structure to hold the compiled prog */
   char error[PCAP_ERRBUF_SIZE];          /* Structure for libpcap errors. */
   
   struct frame x, ic;

   int hopfuzz = 4;
   int network = 0;
   int up = 0;
   int immediate = 1;
   int i,j,k,l,pid;
   float timeout = 60;
   int verify=1;
   int force_sip  = 0;
   int resolve = 0;

   int verbose = 0;
   
   long li,lj;
   struct in_addr temp_ip;
   
   char buf[MX_B], buf2[MX_B], destbuf[1024], rangebuf[1024], portbuf[1024];
   char dest[MX_B];
   char *ttlrange = NULL;
   char *bandwidth = NULL;
   int check_icmp_seq = 0;
   int target_acquired = 0;   
   u_char *seed = malloc(20);
   
   u_char *tcpscan = malloc(MX_B);
   struct libnet_link_int *temp = NULL;

   struct frame *scanx;

   struct timeval start, now, then, diff;

   FILE *targets, *logs;

   prng_state prng;
   pk_initrng(&prng);

   bzero(buf, sizeof(buf));
   bzero(buf2, sizeof(buf2));
      
        if(geteuid() != 0)
        {
                perror("PK requires root to access the network directly.");
                exit(EXIT_FAILURE);
        }

   p = NULL; 
   p = pcap_lookupdev(error);
   if(!p){
      fprintf(stderr, "Couldn't lookup default ethernet device with pcap_lookupdev: %s\n", error);    
      exit(EXIT_FAILURE);
   }
   snprintf(dev, sizeof(dev), "%s", pcap_lookupdev(error));
   
   while ((opt = getopt(argc, argv, "d:i:nNt:b:T:vs:S")) != EOF) {
      switch (opt) {
        case 'd':
           snprintf(dev, sizeof(dev), "%s", optarg);
           break;
        case 'i':
           source_ip = ntohl(libnet_name_resolve(optarg, 0));
           force_sip++;
           break;
        case 'n':
           network++;
           break;
      case 'N':
         resolve++;
         break;
            case 't':
               timeout = atof(optarg);
               break;
        case 'b':
           bandwidth = malloc(1024);
           snprintf(bandwidth, 1024, "%s", optarg);
           break;
      case 'v':
         verbose++;
         break;
      case 's':
         hopfuzz = atoi(optarg);
         break;
      case 'S':
         hopfuzz = -1;
         break;
            default:
               paratrace_usage();
         }
   }           

   if(argv[optind] != NULL)
   {
      snprintf(target, sizeof(target), "%s", argv[optind]);
   } else {
      fprintf(stderr, "Paratrace requires a target to attempt a trace against.\n");
      paratrace_usage();
   }

   if(!force_sip) source_ip=libnet_get_ipaddr(temp, dev, NULL);
   
   if(!bandwidth){
      bandwidth = malloc(1024);
      snprintf(bandwidth, 1024, "0");
      }


   if(verbose)fprintf(stderr, "Stat|=====IP_Address==|Port=|Hops|==Time==|=============Details============|\n");
              fprintf(stderr, "Waiting to detect attachable TCP connection to host/net: %s\n", target);
   gettimeofday(&start, NULL);

   if(!network) snprintf(buf, sizeof(buf), "host");
   else         snprintf(buf, sizeof(buf), "net");
   snprintf(pfprogram, sizeof(pfprogram), "icmp or (src %s %s and tcp)", buf, target);
   pcap = pcap_open_live(dev, 65535, 1, 1, error);
   if(!pcap){
       fprintf(stderr, "Couldn't open device: %s\n", error);
       exit(1);
      }
       
   ioctl(pcap_fileno(pcap), BIOCIMMEDIATE, &immediate);  // prolly breaks nonblock
   
   if (pcap_compile(pcap, &fp, pfprogram, 1, 0x0) == -1) {
      pcap_perror(pcap, "pcap_compile");
      exit(EXIT_FAILURE);
   }
      
   if (pcap_setfilter(pcap, &fp) == -1) {
      pcap_perror(pcap, "pcap_setfilter");
      exit(EXIT_FAILURE);
   }
   gettimeofday(&now, NULL);
   gettimeofday(&then, NULL);

   while(!timeout || now.tv_sec <= (then.tv_sec + timeout))
   {
     packet = (u_char *) pcap_next(pcap, &pkthdr);     
     gettimeofday(&now, NULL); /* packet header sigfigs seem strange */
     if(packet &&
        parse_layers(packet, pkthdr.caplen, &x, 2, pcap_datalink(pcap), 0)){

         /* Accept ICMP packets. */
         
         if(target_acquired &&
            x.ip->ip_p == IPPROTO_ICMP){     
            i=parse_layers((char *)&x.icmp->icmp_data,
                 pkthdr.caplen-LIBNET_ETH_H-(int)x.ip->ip_hl*4-LIBNET_ICMP_H, /* XXX slight chance of bug */
                 &ic, 3, DLT_EN10MB, 1);
              if(i && ic.ip->ip_p == IPPROTO_TCP &&
                 x.icmp->icmp_type == ICMP_TIMXCEED){
                  timeval_subtract(&diff, &pkthdr.ts, &start);
                  gettimeofday(&then, NULL); /* just for the loop maintenance */
                      if(verbose){
                           fprintf(stderr, "Got %i on %s:\n", pkthdr.caplen, dev);
                           fprintf(stderr, " "); print_ip((char *)x.ip);
                     fprintf(stderr, "ICMP: "); print_ip((char *)ic.ip);
                     fprintf(stderr, "ICMP: "); print_tcp((char *)ic.tcp, 1);
                     }
                    bzero(buf, sizeof(buf));
                  bzero(buf2, sizeof(buf2));
                    /* whoa this works?! WTF */
                  snprintf(buf + 0, 16, inet_ntoa(x.ip->ip_src));
                  snprintf(buf +16, 16, inet_ntoa(ic.ip->ip_src));
                  snprintf(buf +32, 16, inet_ntoa(ic.ip->ip_dst));      
                  //fprintf(stdout, "%3.3u = ", 255 - (source_port - ntohs(ic.tcp->th_sport)));
                     fprintf(stdout, "%3.3u = ", htons(ic.ip->ip_id));
                     fprintf(stdout, "%16.16s|%-5i [%2.2hu]", buf,
                             ntohs(ic.tcp->th_dport), estimate_hopcount(x.ip->ip_ttl));
                     fprintf(stdout, "%4lu.%3.3lus", diff.tv_sec, diff.tv_usec/1000);
                     if(resolve==1)
                        fprintf(stdout, "(%35.35s)\n", libnet_host_lookup(x.ip->ip_src.s_addr, 1));
                     else if(resolve==2)
                        fprintf(stdout, "(%35.35s)\n", libnet_host_lookup(ic.ip->ip_dst.s_addr, 1)); 
                     else fprintf(stdout, "(%16.16s -> %-16.16s)\n", buf+16, buf+32);
            }
            else if(target_acquired && 
                    x.icmp->icmp_type == ICMP_UNREACH &&
                    ic.ip->ip_p == IPPROTO_TCP)
               {
                  timeval_subtract(&diff, &pkthdr.ts, &start);
                  gettimeofday(&then, NULL); /* just for the loop maintenance */
                  snprintf(buf2, sizeof(buf2), "un%2.2i", x.icmp->icmp_code);
                  snprintf(buf + 0, 16, inet_ntoa(x.ip->ip_src));
                  snprintf(buf +16, 16, inet_ntoa(ic.ip->ip_src));
                  snprintf(buf +32, 16, inet_ntoa(ic.ip->ip_dst));      
                  fprintf(stdout, "%s: %16.16s:%-5i [%2.2hu]",
                       buf2, buf+32, ntohs(ic.tcp->th_dport),
                       estimate_hopcount(x.ip->ip_ttl)); 
                  fprintf(stdout, "%4lu.%3.3lus", diff.tv_sec, diff.tv_usec/1000);                                                                      
                  if(resolve==1)
                     fprintf(stdout, "(%35.35s)\n", libnet_host_lookup(x.ip->ip_src.s_addr, 1));
                  else if(resolve==2)
                     fprintf(stdout, "(%35.35s)\n", libnet_host_lookup(ic.ip->ip_dst.s_addr, 1));
                  else       fprintf(stdout, "(%16.16s -> %-16.16s)\n", buf+16, buf);              
               }
              
           }
           /* Accept...ummm...anything TCP from target. */
         else if(!up && target_acquired &&
                 x.ip->ip_p == IPPROTO_TCP)
            {
                if(verbose>=2){
                     fprintf(stderr, "Got %i on %s:\n", pkthdr.caplen, dev);
                     fprintf(stderr, " "); print_ip((char *)x.ip);
               fprintf(stderr, " "); print_tcp((char *)x.tcp, 0);
               }
            gettimeofday(&then, NULL); /* just for the loop maintenance */
            bzero(buf, sizeof(buf));
            bzero(buf2, sizeof(buf2));
            timeval_subtract(&diff, &now, &start);
            snprintf(buf2, sizeof(buf2), "  UP"); /* we got SOMETHING */
            if((int)buf2[0]) /* :-P */
               {
               fprintf(stdout, "%s: %16.16s:%-5i [%2.2hu]", buf2, inet_ntoa(x.ip->ip_src), ntohs(x.tcp->th_sport), estimate_hopcount(x.ip->ip_ttl));
               fprintf(stdout, "%4lu.%3.3lus", diff.tv_sec, diff.tv_usec/1000);
               if(resolve)fprintf(stdout, "(%35.35s)\n", libnet_host_lookup(x.ip->ip_src.s_addr, 1));
               else       fprintf(stdout, "\n"); /*fprintf(stdout, "(%29.29s)\n", buf); */
               }
            up++;
            //exit(0); /* gotta figure out to precisely detect the response */
         }
           /* Got an ACK?  Lets trace it back w/ a keepalive, which'll pass all dem stateless filters */
         /* I haven't figured out yet how to detect *hitting* the actual target vs. normal traffic */
         else if(!target_acquired &&
               x.ip->ip_p == IPPROTO_TCP &&
               x.tcp->th_flags == TH_ACK)
            {
            char temp_mac[ETHER_ADDR_LEN];

            target_acquired++;
            if(!ttlrange) ttlrange = malloc(1024);          
            snprintf(ttlrange, 1024, "1-%u", estimate_hopcount(x.ip->ip_ttl)+hopfuzz);                                                                

            snprintf(dest, sizeof(dest), "%s:%u/32", inet_ntoa(x.ip->ip_src), ntohs(x.tcp->th_sport));

            pk_memswp(&(x.eth->ether_dhost), &(x.eth->ether_shost), ETHER_ADDR_LEN);
            pk_memswp(&(x.ip->ip_src), &(x.ip->ip_dst), IPV4_ADDR_LEN);
            pk_memswp(&(x.tcp->th_sport), &(x.tcp->th_dport), 2);
            pk_memswp(&(x.tcp->th_seq), &(x.tcp->th_ack), 4);
                        
            /* zero the payload */
            x.ip->ip_len = htons((int)x.ip->ip_hl*4 + (int)x.tcp->th_off*4);
            pkthdr.caplen = LIBNET_ETH_H + (int)x.ip->ip_hl*4 + (int)x.tcp->th_off*4;
            recalc_checksums(&x, IPPROTO_TCP);

            fprintf(stderr, "%s %s\n", dest, ttlrange);
            pid=0;
            pid=fork();
            if(!pid){
                  usleep(1000); /* wait for OS to deal with that segment first */
                  raw_sock_syn_scan(dest, sizeof(dest), dev, &x,
                                    ttlrange, seed, bandwidth, verbose, resolve, 1);
                        exit(0);
                        }
            }              
         }
              
      }
   }

void paratrace_usage()
{
   fprintf(stderr, "paratrace %s: Parasitic Traceroute via Established TCP Flows & IPID Hopcount\n", VERSION);
   fprintf(stderr, "Component of:  Paketto Keiretsu %s;    Dan Kaminsky  (dan@doxpara.com)\n\n", VERSION);
   fprintf(stderr, "     Example:  paratrace -b100k www.doxpara.com\n");
   fprintf(stderr, "     Example:  paratrace -t0 -n 10.0.1.0/24\n");
   fprintf(stderr, "     Options:  -s  [hopfuzz]: Fuzz hopcount estimation for TTL scan        (+4)\n");
   fprintf(stderr, "               -t  [timeout]: Wait n full seconds for the last response   (60s)\n");   
   fprintf(stderr, "               -b[bandwidth]: Limit bandwidth consumption to n b/k/m/g bytes(0)\n");
   fprintf(stderr, "                              (0 supresses timeouts; maximizes bw utilization)\n");   
   fprintf(stderr, "               -n           : Specify network instead of host to respond to\n");   
   fprintf(stderr, "               -N/-NN       : Enable name resolution (Prefer Source/Dest)\n");   
   fprintf(stderr, "               -v           : Mark packets being sent, as well as received\n");
   fprintf(stderr, "               -vv          : Output full packet traces to stderr\n");      
   fprintf(stderr, "  Addressing:  -d   [device]: Send requests from this L2 hardware device\n");
   fprintf(stderr, "               -i   [source]: Send requests from this L3 IP address\n");
   exit(1);
}

Generated by  Doxygen 1.6.0   Back to index