--- global_structures.h~ Tue Sep 21 13:26:36 1999 +++ global_structures.h Tue Sep 21 13:26:58 1999 @@ -177,6 +177,8 @@ int nullscan; int xmasscan; int fragscan; + int overwritescan; + int overwriteport; int synscan; int windowscan; int maimonscan; --- nmap.c~ Tue Sep 21 12:47:47 1999 +++ nmap.c Tue Sep 21 17:26:13 1999 @@ -86,7 +86,7 @@ if (argc < 2 ) printusage(argv[0]); /* OK, lets parse these args! */ -while((arg = getopt_long(argc,fakeargv,"Ab:D:d::e:Ffg:hIi:M:m:NnOo:P:p:qRrS:s:T:Vv", long_options, &option_index)) != EOF) { +while((arg = getopt_long(argc,fakeargv,"Ab:D:d::e:Ffg:hIi:l:M:m:NnOo:P:p:qRrS:s:T:Vv", long_options, &option_index)) != EOF) { switch(arg) { case 0: if (strcmp(long_options[option_index].name, "max_rtt_timeout") == 0) { @@ -179,6 +179,18 @@ fprintf(o.nmap_stdout, "Reading target specifications from FILE: %s\n", optarg); } break; + case 'l': /* (l)inux ipchains frag scan (i couldn't think of any better) */ + o.overwritescan++; + if (*optarg != '\0') { + if (isdigit((int) *(optarg))) { + o.overwriteport = atoi(optarg); + } else { + fatal("Need integer open port argument to -l, \"%s\" is bogus", optarg); + } + } else { + o.overwriteport = 80; + } + break; case 'M': o.max_parallelism = atoi(optarg); if (o.max_parallelism < 1) fatal("Argument to -M must be at least 1!"); @@ -1618,6 +1630,187 @@ } +/* Much of this is swiped from the send_small_fragz function above */ +int send_overwrite_fragz(int sd, struct in_addr *source, struct in_addr *victim, + unsigned long seq, int sport, int dport, int flags, + int openport) { + +struct pseudo_header { +/*for computing TCP checksum, see TCP/IP Illustrated p. 145 */ + unsigned long s_addy; + unsigned long d_addr; + char zer0; + unsigned char protocol; + unsigned short length; +}; +/*In this placement we get data and some field alignment so we aren't wasting + too much to compute the TCP checksum.*/ + +char packet[sizeof(struct ip) + sizeof(struct tcphdr) + 100]; +struct ip *ip = (struct ip *) packet; +struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ip)); +struct pseudo_header *pseudo = (struct pseudo_header *) (packet + sizeof(struct ip) - sizeof(struct pseudo_header)); +char *frag2 = packet + sizeof(struct ip) + 16; +struct ip *ip2 = (struct ip *) (frag2 - sizeof(struct ip)); +static int myttl = 0; +int res; +struct sockaddr_in sock; +int id; + +if (!myttl) myttl = (time(NULL) % 14) + 51; + +/* It was a tough decision whether to do this here for every packet + or let the calling function deal with it. In the end I grudgingly decided + to do it here and potentially waste a couple microseconds... */ +sethdrinclude(sd); + + +/*Why do we have to fill out this damn thing? This is a raw packet, after all */ +sock.sin_family = AF_INET; +sock.sin_port = htons(dport); + +sock.sin_addr.s_addr = victim->s_addr; + +bzero((char *)packet, sizeof(struct ip) + sizeof(struct tcphdr)); + +/* TCP checksum isn't sent in this packet +pseudo->s_addy = source->s_addr; +pseudo->d_addr = victim->s_addr; +pseudo->protocol = IPPROTO_TCP; +pseudo->length = htons(sizeof(struct tcphdr)); */ + +tcp->th_sport = htons(sport); +tcp->th_dport = htons(openport); +tcp->th_seq = (seq)? htonl(seq) : get_random_uint(); + +tcp->th_off = 5 /*words*/; +tcp->th_flags = flags; + +tcp->th_win = htons(2048); /* Who cares */ + +/* TCP checksum isn't sent in this packet +tcp->th_sum = in_cksum((unsigned short *)pseudo, + sizeof(struct tcphdr) + sizeof(struct pseudo_header)); +*/ +/* Now for the ip header of frag1 */ + +/* TCP checksum isn't sent in this packet +bzero((char *) packet, sizeof(struct ip)); +*/ +ip->ip_v = 4; +ip->ip_hl = 5; +/*RFC 791 allows 8 octet frags, but I get "operation not permitted" (EPERM) + when I try that.*/ +ip->ip_len = BSDFIX(sizeof(struct ip) + 16); /* 16=enough info for firewall */ +id = ip->ip_id = get_random_uint(); +ip->ip_off = BSDFIX(MORE_FRAGMENTS); +ip->ip_ttl = myttl; +ip->ip_p = IPPROTO_TCP; +ip->ip_src.s_addr = source->s_addr; +ip->ip_dst.s_addr = victim->s_addr; + +#if HAVE_IP_IP_SUM +ip->ip_sum= in_cksum((unsigned short *)ip, sizeof(struct ip)); +#endif +if (o.debugging > 1) { + fprintf(o.nmap_stdout, "Raw TCP packet fragment #1 creation completed! Here it is:\n"); + hdump(packet,36); +} +if (o.debugging > 1) + fprintf(o.nmap_stdout, "\nTrying sendto(%d , packet, %d, 0 , %s , %d)\n", + sd, ntohs(ip->ip_len), inet_ntoa(*victim), + (int) sizeof(struct sockaddr_in)); +/* Lets save this and send it AFTER we send the second one, just to be + cute ;) */ + +if ((res = sendto(sd, packet,sizeof(struct ip) + 16 , 0, + (struct sockaddr *)&sock, sizeof(struct sockaddr_in))) == -1) + { + perror("sendto in send_syn_fragz"); + return -1; + } +if (o.debugging > 1) fprintf(o.nmap_stdout, "successfully sent %d bytes of raw_tcp!\n", res); + +/* Now the second fragment overwrites the first fragment */ + +tcp->th_dport = htons(dport); + +pseudo->s_addy = source->s_addr; +pseudo->d_addr = victim->s_addr; +pseudo->protocol = IPPROTO_TCP; +pseudo->length = htons(sizeof(struct tcphdr)); + +tcp->th_sum = in_cksum((unsigned short *)pseudo, + sizeof(struct tcphdr) + sizeof(struct pseudo_header)); + +bzero((char *) packet, sizeof(struct ip)); +ip->ip_v = 4; +ip->ip_hl = 5; +/* here's hoping we don't get an EPERM */ +ip->ip_len = BSDFIX(sizeof(struct ip) + 8); /* we overwrite the dport */ +ip->ip_id = id; +ip->ip_off = BSDFIX(MORE_FRAGMENTS); +ip->ip_ttl = myttl; +ip->ip_p = IPPROTO_TCP; +ip->ip_src.s_addr = source->s_addr; +ip->ip_dst.s_addr = victim->s_addr; + +#if HAVE_IP_IP_SUM +ip->ip_sum= in_cksum((unsigned short *)ip, sizeof(struct ip)); +#endif +if (o.debugging > 1) { + fprintf(o.nmap_stdout, "Raw TCP packet fragment #2 creation completed! Here it is:\n"); + hdump(packet,28); +} +if (o.debugging > 1) + fprintf(o.nmap_stdout, "\nTrying sendto(%d , packet, %d, 0 , %s , %d)\n", + sd, ntohs(ip->ip_len), inet_ntoa(*victim), + (int) sizeof(struct sockaddr_in)); + +if ((res = sendto(sd, packet,sizeof(struct ip) + 8 , 0, + (struct sockaddr *)&sock, sizeof(struct sockaddr_in))) == -1) + { + if (errno == EPERM) + fatal("this scantype will not run on your operating system"); + perror("sendto in send_syn_fragz"); + return -1; + } +if (o.debugging > 1) fprintf(o.nmap_stdout, "successfully sent %d bytes of raw_tcp!\n", res); + + +/* Create the third fragment */ + +bzero((char *) ip2, sizeof(struct ip)); +ip2->ip_v= 4; +ip2->ip_hl = 5; +ip2->ip_len = BSDFIX(sizeof(struct ip) + 4); /* the rest of our TCP packet */ +ip2->ip_id = id; +ip2->ip_off = BSDFIX(2); +ip2->ip_ttl = myttl; +ip2->ip_p = IPPROTO_TCP; +ip2->ip_src.s_addr = source->s_addr; +ip2->ip_dst.s_addr = victim->s_addr; + +#if HAVE_IP_IP_SUM +ip2->ip_sum = in_cksum((unsigned short *)ip2, sizeof(struct ip)); +#endif +if (o.debugging > 1) { + fprintf(o.nmap_stdout, "Raw TCP packet fragment creation completed! Here it is:\n"); + hdump((char *)ip2,24); +} +if (o.debugging > 1) + + fprintf(o.nmap_stdout, "\nTrying sendto(%d , ip2, %d, 0 , %s , %d)\n", sd, + ntohs(ip2->ip_len), inet_ntoa(*victim), (int) sizeof(struct sockaddr_in)); +if ((res = sendto(sd, (void *)ip2,sizeof(struct ip) + 4 , 0, + (struct sockaddr *)&sock, (int) sizeof(struct sockaddr_in))) == -1) + { + perror("sendto in send_tcp_raw frag #2"); + return -1; + } + +return 1; +} portlist super_scan(struct hoststruct *target, unsigned short *portarray, stype scantype) { int initial_packet_width; /* How many scan packets in parallel (to start with) */ int packet_incr = 4; /* How much we increase the parallel packets by each round */ @@ -1806,6 +1999,8 @@ for(decoy=0; decoy < o.numdecoys; decoy++) { if (o.fragscan) send_small_fragz(rawsd, &o.decoys[decoy], &target->host, 0,i, current->portno, scanflags); + else if (o.overwritescan) + send_overwrite_fragz(rawsd, &o.decoys[decoy], &target->host, 0,i, current->portno, scanflags, o.overwriteport); else if (scantype != UDP_SCAN) send_tcp_raw(rawsd, &o.decoys[decoy], &target->host, i, current->portno, 0, 0, scanflags, 0, NULL, 0, @@ -1832,6 +2027,8 @@ for(decoy=0; decoy < o.numdecoys; decoy++) { if (o.fragscan) send_small_fragz(rawsd, &o.decoys[decoy], &target->host, 0, o.magic_port, current->portno, scanflags); + else if (o.overwritescan) + send_overwrite_fragz(rawsd, &o.decoys[decoy], &target->host, 0, o.magic_port, current->portno, scanflags, o.overwriteport); else if (scantype != UDP_SCAN) send_tcp_raw(rawsd, &o.decoys[decoy], &target->host, o.magic_port, current->portno, 0, 0, scanflags, 0, NULL, 0, 0, 0); @@ -2351,6 +2548,8 @@ for(decoy=0; decoy < o.numdecoys; decoy++) { if (o.fragscan) send_small_fragz(rawsd, &o.decoys[decoy], &target->host, sequences[current->trynum],o.magic_port + tries * 3 + current->trynum, current->portno, scanflags); + else if (o.overwritescan) + send_overwrite_fragz(rawsd, &o.decoys[decoy], &target->host, sequences[current->trynum],o.magic_port + tries * 3 + current->trynum, current->portno, scanflags, o.overwriteport); else send_tcp_raw(rawsd, &o.decoys[decoy], &target->host, o.magic_port + tries * 3 + current->trynum, current->portno, sequences[current->trynum], 0, scanflags, 0, NULL, 0,0, 0); @@ -2442,6 +2641,8 @@ for(decoy=0; decoy < o.numdecoys; decoy++) { if (o.fragscan) send_small_fragz(rawsd, &o.decoys[decoy], &target->host, sequences[current->trynum], o.magic_port + tries * 3, current->portno, scanflags); + else if (o.overwritescan) + send_overwrite_fragz(rawsd, &o.decoys[decoy], &target->host, sequences[current->trynum], o.magic_port + tries * 3, current->portno, scanflags, o.overwriteport); else send_tcp_raw(rawsd, &o.decoys[decoy], &target->host, o.magic_port + tries * 3, current->portno, sequences[current->trynum], 0, scanflags, 0, NULL, 0, 0, 0); }