diff -Nru nmap-2.54BETA32-ori/global_structures.h nmap-2.54BETA32/global_structures.h --- nmap-2.54BETA32-ori/global_structures.h Thu Feb 14 02:05:28 2002 +++ nmap-2.54BETA32/global_structures.h Tue Apr 2 16:17:09 2002 @@ -55,6 +55,7 @@ int sd[3]; /* Socket descriptors for connect_scan */ struct timeval sent[3]; int state; + char *comment; int next; /* not struct portinfo * for historical reasons */ int prev; }; @@ -228,6 +229,7 @@ struct ops /* someone took struct options, */ { int debugging; int verbose; + u16 magic_id; /* magic random number, unique for a scan session */ int randomize_hosts; int spoofsource; /* -S used */ struct in_addr *source; @@ -247,6 +249,8 @@ int extra_payload_length; /* These two are for --data_length op */ char *extra_payload; unsigned long host_timeout; + int ttl; /* if 0, normal behaviour. Else, fix ttl and take care about + ICMP time exceeded replies (Phil) */ int scan_delay; int scanflags; /* if not -1, this value should dictate the TCP flags for the core portscaning routine (eg to change a diff -Nru nmap-2.54BETA32-ori/idle_scan.c nmap-2.54BETA32/idle_scan.c --- nmap-2.54BETA32-ori/idle_scan.c Fri Oct 26 08:18:00 2001 +++ nmap-2.54BETA32/idle_scan.c Tue Apr 2 16:17:09 2002 @@ -830,10 +830,10 @@ } if (firstHalfSz == 1 && flatcount1 == 1) - addport(&target->ports, ports[0], IPPROTO_TCP, NULL, PORT_OPEN); + addport(&target->ports, ports[0], IPPROTO_TCP, NULL, PORT_OPEN, NULL); if ((secondHalfSz == 1) && flatcount2 == 1) - addport(&target->ports, ports[firstHalfSz], IPPROTO_TCP, NULL, PORT_OPEN); + addport(&target->ports, ports[firstHalfSz], IPPROTO_TCP, NULL, PORT_OPEN, NULL); return totalfound; } @@ -905,7 +905,7 @@ for(portidx = 0; portidx < numports; portidx++) { if (lookupport(&target->ports, portarray[portidx], IPPROTO_TCP) == NULL) { addport(&target->ports, portarray[portidx], IPPROTO_TCP, NULL, - PORT_CLOSED); + PORT_CLOSED, NULL); } } diff -Nru nmap-2.54BETA32-ori/nmap.c nmap-2.54BETA32/nmap.c --- nmap-2.54BETA32-ori/nmap.c Tue Apr 2 08:57:12 2002 +++ nmap-2.54BETA32/nmap.c Tue Apr 2 16:17:09 2002 @@ -85,6 +85,11 @@ int fd; struct timeval tv; + /* Little option structure initialization */ + o.ttl=0; /* it should already be zero (global variable).. */ + + o.magic_id=get_random_u16(); + /* You never know when "random" numbers will come in handy ... */ gettimeofday(&tv, NULL); srand((tv.tv_sec ^ tv.tv_usec) ^ getpid()); @@ -416,6 +421,7 @@ {"debug", optional_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"max_parallelism", required_argument, 0, 'M'}, + {"ttl", required_argument, 0, 't'}, {"timing", required_argument, 0, 'T'}, {"max_rtt_timeout", required_argument, 0, 0}, {"min_rtt_timeout", required_argument, 0, 0}, @@ -485,7 +491,7 @@ /* OK, lets parse these args! */ optind = 1; /* so it can be called multiple times */ - while((arg = getopt_long_only(argc,fakeargv,"b:D:d::e:Ffg:hIi:M:m:NnOo:P:p:qRrS:s:T:Vv", long_options, &option_index)) != EOF) { + while((arg = getopt_long_only(argc,fakeargv,"b:D:d::t:e:Ffg:hIi: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) { @@ -808,6 +814,11 @@ fatal("Unknown timing mode (-T argment). Use either \"Paranoid\", \"Sneaky\", \"Polite\", \"Normal\", \"Aggressive\", \"Insane\" or a number from 0 (Paranoid) to 5 (Insane)"); } break; + case 't': + o.ttl=atoi(optarg); + if (o.ttl < 1) fatal("Argument to -t must be at least 1!"); + if (o.ttl > 255) fatal("Argument to -t must be at most 255!"); + break; case 'V': printf("\nnmap V. %s\n", NMAP_VERSION); exit(0); @@ -903,6 +914,12 @@ fatal("-P0 (skip ping) is incompatable with -sP (ping scan). If you only want to enumerate hosts, try list scan (-sL)"); } + if ((o.connectscan) && (o.ttl)) { + fatal("You can't set ttl (-t #) with connect scan (-sT). Try another type of scan (-sS is adviced)."); + } + + if (o.ttl) { o.pingtype = PINGTYPE_NONE; } + if (!ports) { if (o.ipprotscan) { ports = getdefaultprots(); diff -Nru nmap-2.54BETA32-ori/osscan.c nmap-2.54BETA32/osscan.c --- nmap-2.54BETA32-ori/osscan.c Tue Apr 2 08:57:12 2002 +++ nmap-2.54BETA32/osscan.c Tue Apr 2 16:17:09 2002 @@ -1420,6 +1420,7 @@ return NULL; } +if (!myttl) myttl = o.ttl; 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 diff -Nru nmap-2.54BETA32-ori/output.c nmap-2.54BETA32/output.c --- nmap-2.54BETA32-ori/output.c Mon Dec 24 21:52:37 2001 +++ nmap-2.54BETA32/output.c Tue Apr 2 16:17:09 2002 @@ -191,7 +191,7 @@ Strncpy(serviceinfo, (service)? service->s_name : "unknown" , sizeof(serviceinfo)); strcpy(rpcmachineinfo, ""); } - log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%-11s%-12s%-24s", portinfo, state, serviceinfo); + log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%-11s%-12s%-24s %s", portinfo, state, serviceinfo,current->comment ? current->comment : ""); log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%s\n", (current->owner)? current->owner : ""); log_write(LOG_MACHINE,"%d/%s/%s/%s/%s/%s//", current->portno, state, diff -Nru nmap-2.54BETA32-ori/portlist.c nmap-2.54BETA32/portlist.c --- nmap-2.54BETA32-ori/portlist.c Sun Dec 30 12:20:08 2001 +++ nmap-2.54BETA32/portlist.c Tue Apr 2 16:17:09 2002 @@ -58,11 +58,11 @@ /* gawd, my next project will be in c++ so I don't have to deal with this crap ... simple linked list implementation */ -int addport(portlist *plist, u16 portno, u8 protocol, char *owner, int state) { +int addport(portlist *plist, u16 portno, u8 protocol, char *owner, int state, char *comment) { struct port *current = NULL; struct port **portarray = NULL; char msg[128]; - + if ((state == PORT_OPEN && o.verbose) || (o.debugging > 1)) { if (owner && *owner) { snprintf(msg, sizeof(msg), " (owner: %s)", owner); @@ -127,6 +127,7 @@ plist->state_counts[state]++; current->state = state; + current->comment = comment; if (protocol == IPPROTO_TCP) { plist->state_counts_tcp[state]++; } else if (protocol == IPPROTO_UDP) { @@ -195,6 +196,8 @@ struct port *tmp; if (pt->owner) free(pt->owner); + if (pt->comment) + free(pt->comment); tmp = freeportlist; freeportlist = pt; pt->next = tmp; @@ -257,8 +260,8 @@ MAX(plist->state_counts[PORT_UNFIREWALLED], plist->state_counts[PORT_CLOSED])) { plist->ignored_port_state = PORT_FIREWALLED; - } else if (plist->state_counts[PORT_UNFIREWALLED] > - plist->state_counts[PORT_CLOSED]) { + } else if ( (plist->state_counts[PORT_UNFIREWALLED] > + plist->state_counts[PORT_CLOSED]) && (!o.ttl)) { plist->ignored_port_state = PORT_UNFIREWALLED; } else plist->ignored_port_state = PORT_CLOSED; } diff -Nru nmap-2.54BETA32-ori/portlist.h nmap-2.54BETA32/portlist.h --- nmap-2.54BETA32-ori/portlist.h Fri Aug 10 07:53:08 2001 +++ nmap-2.54BETA32/portlist.h Tue Apr 2 16:17:09 2002 @@ -79,6 +79,7 @@ unsigned int rpc_lowver; unsigned int rpc_highver; int state; + char *comment; int confidence; /* How sure are we about the state? */ struct port *next; /* Internal use only -- we sometimes like to link them @@ -100,7 +101,7 @@ int numports; /* Total number of ports in list in ANY state */ } portlist; -int addport(portlist *plist, u16 portno, u8 protocol, char *owner, int state); +int addport(portlist *plist, u16 portno, u8 protocol, char *owner, int state, char *comment); int deleteport(portlist *plist, u16 portno, u8 protocol); /* A function for iterating through the ports. Give NULL for the diff -Nru nmap-2.54BETA32-ori/scan_engine.c nmap-2.54BETA32/scan_engine.c --- nmap-2.54BETA32-ori/scan_engine.c Tue Apr 2 08:57:12 2002 +++ nmap-2.54BETA32/scan_engine.c Tue Apr 2 16:17:09 2002 @@ -48,6 +48,27 @@ #include "scan_engine.h" #include "timing.h" + +char *icmp_unreach_code_str[16]={ + "network-unreachable", + "host-unreachable", + "protocol-unreachable", + "port-unreachable", + "fragmentation-needed", + "source-route-failed", + "network-unknown", + "host-unknown", + "network-prohibited", + "host-prohibited", + "TOS-network-unreachable", + "TOS-host-unreachable", + "communication-prohibited", + "host-precedence-violation", + "precedence-cutoff" +}; + + + extern struct ops o; /* predefined filters -- I need to kill these globals at some pont. */ @@ -178,7 +199,7 @@ current->state = newstate; current->next = -1; current->prev = -1; - addport(&target->ports, current->portno, IPPROTO_TCP, owner, newstate); + addport(&target->ports, current->portno, IPPROTO_TCP, owner, newstate, current->comment); return; } @@ -346,10 +367,12 @@ int trynum; int newstate = -1; int i; + int dnat=0; int newport; struct portinfo *current = NULL; struct icmp *icmp; struct ip *ip2; + struct tcphdr *tcp2; u16 *data; struct timeval tv; struct timeval start; @@ -460,6 +483,7 @@ } else if (ip->ip_p == IPPROTO_ICMP) { icmp = (struct icmp *) ((char *)ip + 4 * ip->ip_hl); ip2 = (struct ip *) (((char *) ip) + 4 * ip->ip_hl + 8); + tcp2 = (struct tcphdr *) ((char *)ip2 + 4 * ip2->ip_hl); if (bytes <= 4 * ip->ip_hl + 28U || bytes <= /* IP1len */ 4 * ip->ip_hl + /*ICMPlen */ 8 + /* IP2len */ 4 * ip2->ip_hl + 4U /* TCP ports */) @@ -470,17 +494,30 @@ continue; } + data = (u16 *) ((char *)ip2 + 4 * ip2->ip_hl); + /* log_write(LOG_STDOUT, "Caught ICMP packet:\n"); + hdump(icmp, ntohs(ip->ip_len) - sizeof(struct ip)); */ + + if (o.debugging > 1) + error("Got ICMP type %i code %i",icmp->icmp_type,icmp->icmp_code); + /* Lets ensure this packet relates to a packet to the host we are scanning ... */ + if (ip2->ip_dst.s_addr != target->host.s_addr) { - if (o.debugging > 1) - error("Got an ICMP message which does not relate to a packet sent to the host being scanned"); - continue; - } + newport=ip2->ip_id^o.magic_id; + if ( (portlookup[newport] >=0) && (current=&scan[portlookup[newport]])) { + if (ip2->ip_p== IPPROTO_TCP) { + for(i=0; i < 3; i++) { + if (sequences[i] == ntohl(tcp2->th_seq)) + break; + } + if (i<3) { dnat=1;} + else continue; + } /* other : we assume it's ok, for the moment */ + } else continue; + } else newport = ntohs(data[1]); - data = (u16 *) ((char *)ip2 + 4 * ip2->ip_hl); - /* log_write(LOG_STDOUT, "Caught ICMP packet:\n"); - hdump(icmp, ntohs(ip->ip_len) - sizeof(struct ip)); */ if (icmp->icmp_type == 3) { if (icmp->icmp_code != 0 && icmp->icmp_code != 1 && icmp->icmp_code != 2 && @@ -491,11 +528,12 @@ continue; } - newport = ntohs(data[1]); if (portlookup[newport] >= 0) { current = &scan[portlookup[newport]]; trynum = (current->trynum == 0)? 0 : -1; newstate = PORT_FIREWALLED; + current->comment = malloc(50); + snprintf(current->comment,50,"Blocked (ICMP %s)",icmp_unreach_code_str[icmp->icmp_type]); } else { if (o.debugging) { error("Illegal ICMP type/code 3/%d unreachable packet:", @@ -504,6 +542,16 @@ } continue; } + } + else if ( (icmp->icmp_type == 11) && (o.ttl) ) { + if (portlookup[newport] >= 0) { + current = &scan[portlookup[newport]]; + newstate = PORT_UNFIREWALLED; + if (dnat) { + current->comment = malloc(32); + snprintf(current->comment,32,"DNAT to %s:%i",inet_ntoa(ip2->ip_dst),ntohs(tcp2->th_dport)); + } + } } } /* OK, now we manipulate the port lists and adjust the time */ @@ -613,6 +661,7 @@ scan[i].state = PORT_FRESH; scan[i].portno = portarray[i]; scan[i].trynum = 0; + scan[i].comment = NULL; scan[i].prev = i-1; scan[i].sd[0] = scan[i].sd[1] = scan[i].sd[2] = -1; if (i < numports -1 ) scan[i].next = i+1; @@ -1046,7 +1095,7 @@ /* Consider the ports firewalled */ for( current = pil.firewalled; current ; current = (current->next > -1)? &scan[current->next] : NULL) { - addport(&target->ports, current->portno, IPPROTO_TCP, NULL, PORT_FIREWALLED); + addport(&target->ports, current->portno, IPPROTO_TCP, NULL, PORT_FIREWALLED, current->comment); } pil.testinglist = NULL; } @@ -1175,7 +1224,7 @@ res = recvtime(sd, recvbuf, 2048,10); } if (recvbuf[0] == '1' || recvbuf[0] == '2') { - addport(&target->ports, portarray[i], IPPROTO_TCP, NULL, PORT_OPEN); + addport(&target->ports, portarray[i], IPPROTO_TCP, NULL, PORT_OPEN, NULL); if (recvbuf[0] == '1') { res = recvtime(sd, recvbuf, 2048,5); recvbuf[res] = '\0'; @@ -1191,7 +1240,7 @@ } } else { /* This means the port is closed ... */ - addport(&target->ports, portarray[i], IPPROTO_TCP, NULL, PORT_CLOSED); + addport(&target->ports, portarray[i], IPPROTO_TCP, NULL, PORT_CLOSED, NULL); } } } @@ -1275,6 +1324,7 @@ scan[i].state = PORT_FRESH; scan[i].portno = portarray[i]; scan[i].trynum = 0; + scan[i].comment = NULL; scan[i].prev = i-1; if (i < numports -1 ) scan[i].next = i+1; else scan[i].next = -1; @@ -1627,7 +1677,7 @@ addport(&target->ports, current->portno, (scantype == UDP_SCAN)? IPPROTO_UDP : (scantype == IPPROT_SCAN? IPPROTO_IP: IPPROTO_TCP), - NULL, current->state); + NULL, current->state, current->comment); } } } @@ -1663,11 +1713,11 @@ for (current = openlist; current; current = (current->next >= 0)? &scan[current->next] : NULL) { if (scantype == IPPROT_SCAN) - addport(&target->ports, current->portno, IPPROTO_IP, NULL, PORT_OPEN); + addport(&target->ports, current->portno, IPPROTO_IP, NULL, PORT_OPEN, current->comment); else if (scantype != UDP_SCAN) - addport(&target->ports, current->portno, IPPROTO_TCP, NULL, PORT_OPEN); + addport(&target->ports, current->portno, IPPROTO_TCP, NULL, PORT_OPEN, current->comment); else - addport(&target->ports, current->portno, IPPROTO_UDP, NULL, PORT_OPEN); + addport(&target->ports, current->portno, IPPROTO_UDP, NULL, PORT_OPEN, current->comment); } superscan_timedout: diff -Nru nmap-2.54BETA32-ori/targets.c nmap-2.54BETA32/targets.c --- nmap-2.54BETA32-ori/targets.c Tue Apr 2 08:57:12 2002 +++ nmap-2.54BETA32/targets.c Tue Apr 2 16:17:09 2002 @@ -1376,7 +1376,7 @@ of the ports the user ASKED for */ if (ports && ports->tcp_count == 1 && ports->tcp_ports[0] == newport) addport(&(hostbatch[hostnum].ports), newport, IPPROTO_TCP, NULL, - newportstate); + newportstate,NULL); } } return 0; diff -Nru nmap-2.54BETA32-ori/tcpip.c nmap-2.54BETA32/tcpip.c --- nmap-2.54BETA32-ori/tcpip.c Tue Apr 2 08:57:12 2002 +++ nmap-2.54BETA32/tcpip.c Tue Apr 2 16:17:09 2002 @@ -229,7 +229,7 @@ fatal("send_tcp_raw called with an option length argument of %d which is illegal because it is not divisible by 4", optlen); } - +if (!myttl) myttl = o.ttl; if (!myttl) myttl = (get_random_uint() % 23) + 37; /* It was a tough decision whether to do this here for every packet @@ -307,7 +307,10 @@ ip->ip_v = 4; ip->ip_hl = 5; ip->ip_len = BSDFIX(sizeof(struct ip) + sizeof(struct tcphdr) + optlen + datalen); -get_random_bytes(&(ip->ip_id), 2); +/* magic IPID to help identify ICMP error packets when + * TCP header has been mangled (DNAT, etc.) + * was: get_random_bytes(&(ip->ip_id), 2);*/ +ip->ip_id= dport^o.magic_id; ip->ip_ttl = myttl; ip->ip_p = IPPROTO_TCP; ip->ip_src.s_addr = source->s_addr; @@ -506,6 +509,7 @@ } +if (!myttl) myttl = o.ttl; if (!myttl) myttl = (get_random_uint() % 23) + 37; /* It was a tough decision whether to do this here for every packet @@ -565,7 +569,10 @@ ip->ip_v = 4; ip->ip_hl = 5; ip->ip_len = BSDFIX(sizeof(struct ip) + sizeof(udphdr_bsd) + datalen); -get_random_bytes(&(ip->ip_id), 2); +/* magic IPID to help identify ICMP error packets when + * TCP header has been mangled (DNAT, etc.) + * was: get_random_bytes(&(ip->ip_id), 2);*/ +ip->ip_id= dport^o.magic_id; ip->ip_ttl = myttl; ip->ip_p = IPPROTO_UDP; ip->ip_src.s_addr = source->s_addr; @@ -628,6 +635,7 @@ struct sockaddr_in sock; int id; +if (!myttl) myttl = o.ttl; if (!myttl) myttl = (time(NULL) % 14) + 51; /* It was a tough decision whether to do this here for every packet @@ -669,7 +677,10 @@ /*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); -id = ip->ip_id = get_random_uint(); +/* magic IPID to help identify ICMP error packets when + * TCP header has been mangled (DNAT, etc.) + * was: id = ip->ip_id = get_random_uint(); */ +id = ip->ip_id = dport^o.magic_id; ip->ip_off = BSDFIX(MORE_FRAGMENTS); ip->ip_ttl = myttl; ip->ip_p = IPPROTO_TCP; @@ -768,6 +779,7 @@ return -1; } +if (!myttl) myttl = o.ttl; if (!myttl) myttl = (get_random_uint() % 23) + 37; /* It was a tough decision whether to do this here for every packet diff -Nru nmap-2.54BETA32-ori/utils.c nmap-2.54BETA32/utils.c --- nmap-2.54BETA32-ori/utils.c Thu Mar 21 07:39:49 2002 +++ nmap-2.54BETA32/utils.c Tue Apr 2 16:17:09 2002 @@ -183,6 +183,12 @@ return i; } +u16 get_random_u16() { + u16 i; + get_random_bytes(&i, sizeof(i)); + return i; +} + u8 get_random_u8() { u8 i; get_random_bytes(&i, sizeof(i)); diff -Nru nmap-2.54BETA32-ori/utils.h nmap-2.54BETA32/utils.h --- nmap-2.54BETA32-ori/utils.h Sun Dec 30 13:16:22 2001 +++ nmap-2.54BETA32/utils.h Tue Apr 2 16:17:09 2002 @@ -135,6 +135,7 @@ unsigned short get_random_ushort(); unsigned int get_random_uint(); u32 get_random_u32(); +u16 get_random_u16(); u8 get_random_u8(); /* Scramble the contents of an array*/