Index: NmapOps.cc =================================================================== --- NmapOps.cc (revision 30909) +++ NmapOps.cc (working copy) @@ -533,7 +533,7 @@ fatal("--min-rate=%g must be less than or equal to --max-rate=%g", min_packet_send_rate, max_packet_send_rate); } - if (af() == AF_INET6 && (generate_random_ips|numdecoys|bouncescan|fragscan|idlescan)) { + if (af() == AF_INET6 && (generate_random_ips|numdecoys|bouncescan|fragscan)) { fatal("Sorry -- IPv6 support is currently only available for TCP, UDP, and SCTP port scans and list scan (-sL). OS detection, random targets and decoys are also not supported with IPv6. Further support is under consideration."); } Index: idle_scan.cc =================================================================== --- idle_scan.cc (revision 30909) +++ idle_scan.cc (working copy) @@ -115,7 +115,7 @@ struct idle_proxy_info { Target host; /* contains name, IP, source IP, timing info, etc. */ int seqclass; /* IP ID sequence class (IPID_SEQ_* defined in nmap.h) */ - u16 latestid; /* The most recent IP ID we have received from the proxy */ + u32 latestid; /* The most recent IP ID we have received from the proxy */ u16 probe_port; /* The port we use for probing IP ID infoz */ u16 max_groupsz; /* We won't test groups larger than this ... */ u16 min_groupsz; /* We won't allow the group size to fall below this @@ -143,7 +143,7 @@ Proxy timing is adjusted, but proxy->latestid is NOT ADJUSTED -- you'll have to do that yourself. Probes_sent is set to the number of probe packets sent during execution */ -static int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent, +static long ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent, int *probes_rcvd) { struct timeval tv_end; int tries = 0; @@ -151,7 +151,7 @@ int sent = 0, rcvd = 0; int maxtries = 3; /* The maximum number of tries before we give up */ struct timeval tv_sent[3], rcvdtime; - int ipid = -1; + long ipid = -1; int to_usec; unsigned int bytes; int base_port; @@ -161,6 +161,16 @@ static u32 ack = 0; static int packet_send_count = 0; /* Total # of probes sent by this program -- to ensure that our sequence # always changes */ + /* new things we need for ipv6 */ + u32 packetlen = 0; + u8 ip6hdr; + struct ip6_ext_data_fragment *frag_header = NULL; + u8 *ping = NULL; + struct sockaddr_storage ss; + size_t sslen; + void *ip6data; + struct ip6_hdr *ip6; + if (o.magic_port_set) base_port = o.magic_port; else @@ -176,14 +186,28 @@ gettimeofday(&tv_sent[tries], NULL); /* Time to send the pr0be!*/ - send_tcp_raw(proxy->rawsd, proxy->ethptr, - proxy->host.v4sourceip(), proxy->host.v4hostip(), - o.ttl, false, - o.ipoptions, o.ipoptionslen, - base_port + tries, proxy->probe_port, - seq_base + (packet_send_count++ * 500) + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, - (u8 *) "\x02\x04\x05\xb4", 4, - NULL, 0); + if (proxy->host.af() == AF_INET6){ + int rc = resolve(proxy->host.HostName(), 0, &ss, &sslen, o.pf()); + if (rc != 0) { + fatal("Could not resolve idle scan zombie host \"%s\": %s", proxy->host.HostName(), gai_strerror(rc)); + } + ping = build_tcp_raw_ipv6(proxy->host.v6sourceip(), proxy->host.v6hostip(), + 0x00, 0x0000, o.ttl, + base_port + tries, proxy->probe_port, + seq_base + (packet_send_count++ * 500) + 1, ack, + 0, TH_SYN | TH_ACK, 0, 0, + (u8 *) "\x02\x04\x05\xb4", 4, + NULL, 0, &packetlen); + send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ping, packetlen); + }else + send_tcp_raw(proxy->rawsd, proxy->ethptr, + proxy->host.v4sourceip(), proxy->host.v4hostip(), + o.ttl, false, + o.ipoptions, o.ipoptionslen, + base_port + tries, proxy->probe_port, + seq_base + (packet_send_count++ * 500) + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, + (u8 *) "\x02\x04\x05\xb4", 4, + NULL, 0); sent++; tries++; @@ -195,19 +219,28 @@ to_usec = proxy->host.to.timeout - TIMEVAL_SUBTRACT(tv_end, tv_sent[tries - 1]); if (to_usec < 0) to_usec = 0; // Final no-block poll - ip = (struct ip *) readipv4_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); + if (proxy->host.af() == AF_INET6) + ip = (struct ip *) readip_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); + else + ip = (struct ip *) readipv4_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); gettimeofday(&tv_end, NULL); + //TODO: optimize that, a lot of things are here twice if (ip) { - if (bytes < ( 4 * ip->ip_hl) + 14U) - continue; + if (ip->ip_v == 6){ + ip6 = (struct ip6_hdr *) ip; + if (ip6->ip6_nxt!=44) + fatal("IPv6 packet without fragmentation header received - issues with the zombie?"); + //for some reason we need to add 2 here, have to figure out why + frag_header = (struct ip6_ext_data_fragment *)((u_char *)ip6 + IP6_HDR_LEN + 2); + //TODO: check if the next header in the frag header says TCP + //for now, we do this manually, ipv6_get_data_any sometimes return null... + tcp = (struct tcp_hdr *)((u_char * )ip6 + IP6_HDR_LEN + 8); + //ip6data = (void *) ipv6_get_data_any(ip6, &packetlen, &ip6hdr); - if (ip->ip_p == IPPROTO_TCP) { - - tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl)); if (ntohs(tcp->th_dport) < base_port || ntohs(tcp->th_dport) - base_port >= tries || ntohs(tcp->th_sport) != proxy->probe_port || ((tcp->th_flags & TH_RST) == 0)) { if (ntohs(tcp->th_dport) > o.magic_port && ntohs(tcp->th_dport) < (o.magic_port + 260)) { if (o.debugging) { - error("Received IP ID zombie probe response which probably came from an earlier prober instance ... increasing rttvar from %d to %d", + error("IPv6: Received IP ID zombie probe response which probably came from an earlier prober instance ... increasing rttvar from %d to %d", proxy->host.to.rttvar, (int) (proxy->host.to.rttvar * 1.2)); } proxy->host.to.rttvar = (int) (proxy->host.to.rttvar * 1.2); @@ -218,12 +251,38 @@ } continue; } - trynum = ntohs(tcp->th_dport) - base_port; rcvd++; - ipid = ntohs(ip->ip_id); + ipid = ntohl(frag_header->ident); adjust_timeouts2(&(tv_sent[trynum]), &rcvdtime, &(proxy->host.to)); + }else{ + if (bytes < ( 4 * ip->ip_hl) + 14U) + continue; + + if (ip->ip_p == IPPROTO_TCP) { + + tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl)); + if (ntohs(tcp->th_dport) < base_port || ntohs(tcp->th_dport) - base_port >= tries || ntohs(tcp->th_sport) != proxy->probe_port || ((tcp->th_flags & TH_RST) == 0)) { + if (ntohs(tcp->th_dport) > o.magic_port && ntohs(tcp->th_dport) < (o.magic_port + 260)) { + if (o.debugging) { + error("Received IP ID zombie probe response which probably came from an earlier prober instance ... increasing rttvar from %d to %d", + proxy->host.to.rttvar, (int) (proxy->host.to.rttvar * 1.2)); + } + proxy->host.to.rttvar = (int) (proxy->host.to.rttvar * 1.2); + rcvd++; + } else if (o.debugging > 1) { + error("Received unexpected response packet from %s during IP ID zombie probing:", inet_ntoa(ip->ip_src)); + readtcppacket( (unsigned char *) ip, MIN(ntohs(ip->ip_len), bytes)); + } + continue; + } + trynum = ntohs(tcp->th_dport) - base_port; + rcvd++; + + ipid = ntohs(ip->ip_id); + adjust_timeouts2(&(tv_sent[trynum]), &rcvdtime, &(proxy->host.to)); + } } } } @@ -233,7 +292,6 @@ *probes_sent = sent; if (probes_rcvd) *probes_rcvd = rcvd; - return ipid; } @@ -242,15 +300,17 @@ one, assuming the given IP ID Sequencing class. Returns -1 if the distance cannot be determined */ -static int ipid_distance(int seqclass , u16 startid, u16 endid) { +/*again, we need to upgrade from 16 to 32 bit for ipv6 compatibility */ +static long ipid_distance(int seqclass , u32 startid, u32 endid) { if (seqclass == IPID_SEQ_INCR) return endid - startid; + //for me, htonl is not necessary, instead diving by 2 if (seqclass == IPID_SEQ_BROKEN_INCR) { /* Convert to network byte order */ - startid = htons(startid); - endid = htons(endid); - return endid - startid; + //startid = htonl(startid); + //endid = htonl(endid); + return (endid - startid)/2; } return -1; @@ -274,15 +334,15 @@ the program */ #define NUM_IPID_PROBES 6 static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, - const struct in_addr *first_target, const struct scan_lists *ports) { + Target *target, const struct scan_lists *ports) { int probes_sent = 0, probes_returned = 0; int hardtimeout = 9000000; /* Generally don't wait more than 9 secs total */ unsigned int bytes, to_usec; int timedout = 0; - char *p, *q; + char *p, *q, *r; char *endptr = NULL; int seq_response_num; - int newipid; + long newipid; int i; char filter[512]; /* Libpcap filter string */ char name[MAXHOSTNAMELEN + 1]; @@ -291,15 +351,36 @@ u32 sequence_base; u32 ack = 0; struct timeval probe_send_times[NUM_IPID_PROBES], tmptv, rcvdtime; - u16 lastipid = 0; + /*ipid of IPv6 has 32 bit */ + u32 lastipid = 0; struct ip *ip; struct tcp_hdr *tcp; int distance; - int ipids[NUM_IPID_PROBES]; + long ipids[NUM_IPID_PROBES]; u8 probe_returned[NUM_IPID_PROBES]; struct route_nfo rnfo; assert(proxy); assert(proxyName); + u8 *ping = NULL; + char data[1218]; //the maximum we can do without fragmenting our ping + const void *rdata; //the data received in the echo response + unsigned int datalen; + u32 packetlen = 0; + struct abstract_ip_hdr hdr; + bool response_received = false; + struct ppkt { + unsigned char type; + unsigned char code; + unsigned short checksum; + unsigned short id; + unsigned short seq; + } *icmp6; + u16 pingid = 0; + u16 seq = 0; + const struct ip6_hdr *ip6; + u8 ip6hdr; + const void *ip6data; + struct ip6_ext_data_fragment *frag_header = NULL; ack = get_random_u32(); @@ -314,7 +395,17 @@ proxy->max_senddelay = 100000; Strncpy(name, proxyName, sizeof(name)); + //TODO: If we have an IPv6 address, we don't know if the last colon-seperated part is the port or part of the address + /* In IPv6, we have colons in the address, so we just look for the last one */ + r = NULL; q = strchr(name, ':'); + while (q!=NULL){ + r = q; + q = strchr(q+1, ':'); + } + /*get the last valid occurence of the colon */ + q = r; + if (q) { *q++ = '\0'; proxy->probe_port = strtoul(q, &endptr, 10); @@ -342,6 +433,7 @@ if (rc != 0) { fatal("Could not resolve idle scan zombie host \"%s\": %s", name, gai_strerror(rc)); } + proxy->host.setTargetSockAddr(&ss, sslen); /* Lets figure out the appropriate source address to use when sending @@ -392,16 +484,99 @@ proxy->ethptr = NULL; } + if (proxy->host.af()==AF_INET6) + { + /* First, we force the proxy to provide is with a fragmentation header in each packet + To do so, we first send a big ping, and then send an ICMPv6 Packet Too Big and say + that the packet was too big, needs to be smaller than 1280 byte */ + //Normally, I use a lot of data, but because that would mean to implement fragmentation for IPv6, we leave it a bit smaller + for( i = 0 ; i < sizeof(data) ; i++) + data[i] = 'A'; + pingid = get_random_u16(); + seq = get_random_u16(); + + /* pcap, to get the answer. Max size her is the IPv6 minimum MTU, 1280 */ + if ((proxy->pd = my_pcap_open_live(proxy->host.deviceName(), 1280, (o.spoofsource) ? 1 : 0, 50)) == NULL) + fatal("%s", PCAP_OPEN_ERRMSG); + p = strdup(proxy->host.targetipstr()); + /* We need something that works for IPv4 and IPv6 */ + q = strdup(proxy->host.sourceipstr()); + + Snprintf(filter, sizeof(filter), "icmp6 and src host %s and dst host %s", p, q); + free(p); + free(q); + if (o.debugging) + log_write(LOG_STDOUT, "Packet capture filter (device %s): %s\n", proxy->host.deviceFullName(), filter); + + + //Make a ping with the maximum possible size and send it + ping = build_icmpv6_raw(proxy->host.v6sourceip(), proxy->host.v6hostip(), 0x00, 0x0000, o.ttl, seq , pingid, ICMPV6_ECHO, 0x00, data, sizeof(data) , &packetlen); + send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ping, packetlen); + free(ping); + + /* Now lets wait for the answer */ + while (!response_received){ + to_usec = 2000; + ip = (struct ip *) readip_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); + if (!ip) + continue; + datalen = bytes; + rdata = ip_get_data(ip, &datalen, &hdr); + if (hdr.proto == IPPROTO_ICMPV6){ + icmp6 = (struct ppkt *) rdata; + if (icmp6->type == ICMPV6_ECHOREPLY) //we should also check for data, seq and id (watch out for big/little endian + response_received=true; + //error("type: %d, code: %d, checksum: %x, id: %x, recvd seq: %d || pingid: %d, seq: %d", icmp6->type, icmp6->code, icmp6->checksum, icmp6->id, icmp6->seq, pingid, seq); + } + } + + /*Now we can tell the decoy host that its reply was too big, we want smaller than the IPV6 minimum MTU */ + /* the data contains first the MTU we want, and then the received IPv6 package */ + data[0]=0; data[1]=0; data[2]=0x04; data[3]=0xfe; + memcpy(&data[4], ip, sizeof(data)-4); + + ping = build_icmpv6_raw(proxy->host.v6sourceip(), proxy->host.v6hostip(), 0x00, 0x0000, o.ttl, 0x00 , 0x00, 0x02, 0x00, data, sizeof(data) , &packetlen); + send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ping, packetlen); + free(ping); + + /* Now we do the same in the name of the target */ + /* No pcap this time, we won't receive the answer */ + for( i = 0 ; i < sizeof(data) ; i++) + data[i] = 'A'; + pingid = get_random_u16(); + seq = get_random_u16(); + + ping = build_icmpv6_raw(target->v6hostip(), proxy->host.v6hostip(), 0x00, 0x0000, o.ttl, seq , pingid, ICMPV6_ECHO, 0x00, data, sizeof(data) , &packetlen); + send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ping, packetlen); + free(ping); + + /* Now we guess what answer the decoy host sent to the target, so that we can piggyback this on the ICMPV6 Packet too Big message */ + ping = build_icmpv6_raw(proxy->host.v6hostip(), target->v6hostip(), 0x00, 0x0000, o.ttl, seq , pingid, ICMPV6_ECHOREPLY, 0x00, data, sizeof(data) , &packetlen); + data[0]=0; data[1]=0; data[2]=0x04; data[3]=0xfe; + memcpy(&data[4], ping, sizeof(data)-4); + free(ping); + + ping = build_icmpv6_raw(target->v6hostip(), proxy->host.v6hostip(), 0x00, 0x0000, o.ttl, 0x00 , 0x00, 0x02, 0x00, data, sizeof(data) , &packetlen); + /* give the decoy host time to reply to the target */ + usleep(30000); + send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ping, packetlen); + free(ping); + } + /* Now for the pcap opening nonsense ... */ /* Note that the snaplen is 152 = 64 byte max IPhdr + 24 byte max link_layer * header + 64 byte max TCP header. */ + // TODO: An IPv6 header might be bigger due to all the extension headers, but if theres only the one for fragmentation, is 48 byte if ((proxy->pd = my_pcap_open_live(proxy->host.deviceName(), 152, (o.spoofsource) ? 1 : 0, 50)) == NULL) fatal("%s", PCAP_OPEN_ERRMSG); p = strdup(proxy->host.targetipstr()); - q = strdup(inet_ntoa(proxy->host.v4source())); - Snprintf(filter, sizeof(filter), "tcp and src host %s and dst host %s and src port %hu", p, q, proxy->probe_port); + /* We need something that works for IPv4 and IPv6 */ + q = strdup(proxy->host.sourceipstr()); + /* libpcap doesn't find the source port in IPv6 if theres a fragmentation header. Therefore we use this ugly hack to state the source port */ + //TODO: what do we do if there are multiple extension headers? + Snprintf(filter, sizeof(filter), "tcp and src host %s and dst host %s and src port %hu or (ip6[6]=44 and ip6[40]=6 and ip6[48:2]=%hu)", p, q, proxy->probe_port, proxy->probe_port); free(p); free(q); set_pcap_filter(proxy->host.deviceFullName(), proxy->pd, filter); @@ -426,14 +601,27 @@ a response with the exact request for timing purposes. So I think I'll use TH_SYN, although it is a tough call. */ /* We can't use decoys 'cause that would screw up the IP IDs */ - send_tcp_raw(proxy->rawsd, proxy->ethptr, - proxy->host.v4sourceip(), proxy->host.v4hostip(), - o.ttl, false, - o.ipoptions, o.ipoptionslen, - o.magic_port + probes_sent + 1, proxy->probe_port, - sequence_base + probes_sent + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, - (u8 *) "\x02\x04\x05\xb4", 4, - NULL, 0); + /* Now we make a difference between IPv4 and IPv6 */ + if (proxy->host.af() == AF_INET) + send_tcp_raw(proxy->rawsd, proxy->ethptr, + proxy->host.v4sourceip(), proxy->host.v4hostip(), + o.ttl, false, + o.ipoptions, o.ipoptionslen, + o.magic_port + probes_sent + 1, proxy->probe_port, + sequence_base + probes_sent + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, + (u8 *) "\x02\x04\x05\xb4", 4, + NULL, 0); + else if (proxy->host.af() == AF_INET6){ + ping = build_tcp_raw_ipv6(proxy->host.v6sourceip(), proxy->host.v6hostip(), + 0x00, 0x0000, o.ttl, + o.magic_port + probes_sent + 1, proxy->probe_port, + sequence_base + probes_sent + 1, ack, + 0, TH_SYN | TH_ACK, 0, 0, + (u8 *) "\x02\x04\x05\xb4", 4, + NULL, 0, &packetlen); + send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ping, packetlen); + } + gettimeofday(&probe_send_times[probes_sent], NULL); probes_sent++; @@ -441,13 +629,19 @@ while (probes_returned < probes_sent && !timedout) { to_usec = (probes_sent == NUM_IPID_PROBES) ? hardtimeout : 1000; - ip = (struct ip *) readipv4_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); + /* again, we differ between ipv4 and ipv6 */ + if (proxy->host.af() == AF_INET6){ + ip = (struct ip *) readip_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); + }else{ + ip = (struct ip *) readipv4_pcap(proxy->pd, &bytes, to_usec, &rcvdtime, NULL, true); + } gettimeofday(&tmptv, NULL); - if (!ip) { - if (probes_sent < NUM_IPID_PROBES) + if (!ip){ + if (probes_sent < NUM_IPID_PROBES){ break; + } if (TIMEVAL_SUBTRACT(tmptv, probe_send_times[probes_sent - 1]) >= hardtimeout) { timedout = 1; } @@ -456,19 +650,24 @@ timedout = 1; } - if (lastipid != 0 && ip->ip_id == lastipid) { - continue; /* probably a duplicate */ - } - lastipid = ip->ip_id; + if (ip->ip_v == 6){//proxy->host.af() == AF_INET6){ + ip6 = (struct ip6_hdr *) ip; + if (ip6->ip6_nxt!=44) + fatal("IPv6 packet without fragmentation header received - issues with the zombie?"); + //for some reason we need to add 2 here, have to figure out why + frag_header = (struct ip6_ext_data_fragment *)((u_char *)ip6 + IP6_HDR_LEN + 2); + + /* now that the additional ipv6 stuff is doen, we continue similar */ + if (lastipid != 0 && frag_header->ident == lastipid) { + continue; /* probably a duplicate */ + } + lastipid = frag_header->ident; - if (bytes < ( 4 * ip->ip_hl) + 14U) - continue; - - if (ip->ip_p == IPPROTO_TCP) { - tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl)); + ip6data = ipv6_get_data_any(ip6, &packetlen, &ip6hdr); + tcp = (struct tcp_hdr *) ip6data; if (ntohs(tcp->th_dport) < (o.magic_port + 1) || ntohs(tcp->th_dport) - o.magic_port > NUM_IPID_PROBES || ntohs(tcp->th_sport) != proxy->probe_port || ((tcp->th_flags & TH_RST) == 0)) { if (o.debugging > 1) - error("Received unexpected response packet from %s during initial IP ID zombie testing", inet_ntoa(ip->ip_src)); + error("Received unexpected response packet from %s during initial IP ID zombie testing", inet_ntoa(ip->ip_src)); continue; } @@ -479,9 +678,39 @@ of sneaking through the firewall. Plus SYN|ACK is what they will be receiving back from the target */ probes_returned++; - ipids[seq_response_num] = (u16) ntohs(ip->ip_id); + ipids[seq_response_num] = (u32) ntohl(frag_header->ident); probe_returned[seq_response_num] = 1; adjust_timeouts2(&probe_send_times[seq_response_num], &rcvdtime, &(proxy->host.to)); + + }else{ + if (lastipid != 0 && ip->ip_id == lastipid) { + continue; /* probably a duplicate */ + } + lastipid = ip->ip_id; + + if (bytes < ( 4 * ip->ip_hl) + 14U) + continue; + + if (ip->ip_p == IPPROTO_TCP) { + tcp = ((struct tcp_hdr *) (((char *) ip) + 4 * ip->ip_hl)); + if (ntohs(tcp->th_dport) < (o.magic_port + 1) || ntohs(tcp->th_dport) - o.magic_port > NUM_IPID_PROBES || ntohs(tcp->th_sport) != proxy->probe_port || ((tcp->th_flags & TH_RST) == 0)) { + if (o.debugging > 1) + error("Received unexpected response packet from %s during initial IP ID zombie testing", inet_ntoa(ip->ip_src)); + continue; + } + + seq_response_num = probes_returned; + + /* The stuff below only works when we send SYN packets instead of + SYN|ACK, but then are slightly less stealthy and have less chance + of sneaking through the firewall. Plus SYN|ACK is what they will + be receiving back from the target */ + probes_returned++; + /* we made the ipid array bigger in order to also match for IPv6 */ + ipids[seq_response_num] = (u32) ntohs(ip->ip_id); + probe_returned[seq_response_num] = 1; + adjust_timeouts2(&probe_send_times[seq_response_num], &rcvdtime, &(proxy->host.to)); + } } } } @@ -494,7 +723,7 @@ probes_returned++; } } - + if (probes_returned == 0) fatal("Idle scan zombie %s (%s) port %hu cannot be used because it has not returned any of our probes -- perhaps it is down or firewalled.", proxy->host.HostName(), proxy->host.targetipstr(), @@ -533,19 +762,31 @@ changed. This will also catch the case where the Nmap user is behind an egress filter or other measure that prevents this sort of sp00fery */ - if (first_target) { + /* this behavior gets quite common in IPv6 so now its even more important to check */ + if (target->v4hostip() || target->v6hostip()) { for (probes_sent = 0; probes_sent < 4; probes_sent++) { if (probes_sent != 0) usleep(50000); - send_tcp_raw(proxy->rawsd, proxy->ethptr, - first_target, proxy->host.v4hostip(), - o.ttl, false, - o.ipoptions, o.ipoptionslen, - o.magic_port, proxy->probe_port, - sequence_base + probes_sent + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, - (u8 *) "\x02\x04\x05\xb4", - 4, NULL, 0); - + if (target->v4hostip()) + send_tcp_raw(proxy->rawsd, proxy->ethptr, + target->v4hostip(), proxy->host.v4hostip(), + o.ttl, false, + o.ipoptions, o.ipoptionslen, + o.magic_port, proxy->probe_port, + sequence_base + probes_sent + 1, ack, 0, TH_SYN | TH_ACK, 0, 0, + (u8 *) "\x02\x04\x05\xb4", + 4, NULL, 0); + else{ + ping = build_tcp_raw_ipv6(target->v6hostip(), proxy->host.v6hostip(), + 0x00, 0x0000, o.ttl, + o.magic_port + probes_sent + 1, proxy->probe_port, + sequence_base + probes_sent + 1, ack, + 0, TH_SYN | TH_ACK, 0, 0, + (u8 *) "\x02\x04\x05\xb4", 4, + NULL, 0, &packetlen); + send_ip_packet(proxy->rawsd, proxy->ethptr, &ss, ping, packetlen); + } + } /* Sleep a little while to give packets time to reach their destination */ @@ -556,7 +797,7 @@ if (newipid < 0) fatal("Your IP ID Zombie (%s; %s) is behaving strangely -- suddenly cannot obtain IP ID", proxy->host.HostName(), proxy->host.targetipstr()); - + distance = ipid_distance(proxy->seqclass, proxy->latestid, newipid); if (distance <= 0) { fatal("Your IP ID Zombie (%s; %s) is behaving strangely -- suddenly cannot obtain valid IP ID distance.", proxy->host.HostName(), proxy->host.targetipstr()); @@ -567,8 +808,8 @@ error("WARNING: IP ID spoofing test sent 4 packets and expected a distance of 5, but instead got %d", distance); } proxy->latestid = newipid; + } - } @@ -655,15 +896,29 @@ struct timeval probe_times[4]; int pr0be; static u32 seq = 0; - int newipid = 0; + //again, because its IPv6 + long newipid = 0; int sleeptime; int lasttry = 0; int dotry3 = 0; struct eth_nfo eth; + //we need some things for ipv6 + u8 *packet = NULL; + struct sockaddr_storage ss; + size_t sslen; + u32 packetlen = 0; + if (seq == 0) seq = get_random_u32(); + if (proxy->host.af() == AF_INET6){ + int rc = resolve(target->HostName(), 0, &ss, &sslen, o.pf()); + if (rc != 0) + fatal("Could not resolve target \"%s\": %s", proxy->host.HostName(), gai_strerror(rc)); + } + + memset(&end, 0, sizeof(end)); memset(&latestchange, 0, sizeof(latestchange)); gettimeofday(&start, NULL); @@ -692,13 +947,26 @@ but doing it the straightforward way (using the same decoys as we use in probing the proxy box is risky. I'll have to think about this more. */ - send_tcp_raw(proxy->rawsd, eth.ethsd ? ð : NULL, - proxy->host.v4hostip(), target->v4hostip(), - o.ttl, false, - o.ipoptions, o.ipoptionslen, - proxy->probe_port, ports[pr0be], seq, 0, 0, TH_SYN, 0, 0, - (u8 *) "\x02\x04\x05\xb4", 4, - o.extra_payload, o.extra_payload_length); + if (target->v4hostip()) + send_tcp_raw(proxy->rawsd, eth.ethsd ? ð : NULL, + proxy->host.v4hostip(), target->v4hostip(), + o.ttl, false, + o.ipoptions, o.ipoptionslen, + proxy->probe_port, ports[pr0be], seq, 0, 0, TH_SYN, 0, 0, + (u8 *) "\x02\x04\x05\xb4", 4, + o.extra_payload, o.extra_payload_length); + + else{ + packet = build_tcp_raw_ipv6(proxy->host.v6hostip(), target->v6hostip(), + 0x00, 0x0000, o.ttl, + proxy->probe_port, ports[pr0be], + seq, 0, + 0, TH_SYN, 0, 0, + (u8 *) "\x02\x04\x05\xb4", 4, + o.extra_payload, o.extra_payload_length, &packetlen); + send_ip_packet(proxy->rawsd, eth.ethsd ? ð : NULL, &ss, packet, packetlen); + } + } gettimeofday(&end, NULL); @@ -863,8 +1131,6 @@ flatcount1 = idlescan_countopen(proxy, target, ports, firstHalfSz, &sentTime1, &rcvTime1); - - if (firstHalfSz > 1 && flatcount1 > 0) { /* A port appears open! We dig down deeper to find it ... */ deepcount1 = idle_treescan(proxy, target, ports, firstHalfSz, flatcount1); @@ -971,8 +1237,6 @@ } - - /* The very top-level idle scan function -- scans the given target host using the given proxy -- the proxy is cached so that you can keep calling this function with different targets */ @@ -1009,7 +1273,7 @@ /* If this is the first call, */ if (!*lastproxy) { - initialize_idleproxy(&proxy, proxyName, target->v4hostip(), ports); + initialize_idleproxy(&proxy, proxyName, target, ports); strncpy(lastproxy, proxyName, sizeof(lastproxy)); } Index: osscan2.cc =================================================================== --- osscan2.cc (revision 30909) +++ osscan2.cc (working copy) @@ -217,8 +217,9 @@ This islocalhost argument is a boolean specifying whether these numbers were generated by scanning localhost. NOTE: the "ipids" argument may be modified if localhost is set to true. */ -int get_ipid_sequence(int numSamples, int *ipids, int islocalhost) { - u16 ipid_diffs[32]; +/* we have to change the ipids from u16 to u32 in order to also save ipv6 ipids */ +int get_ipid_sequence(int numSamples, long *ipids, int islocalhost) { + u32 ipid_diffs[32]; int i, j, k; int allipideqz = 1; /* Flag that means "All IP.IDs returned during sequencing * are zero. This is unset if we find a nonzero */ @@ -290,7 +291,8 @@ k = 1; /* k is a flag meaning "all difference seen are multiples of 256 and * no greater than 5120" */ for (i = 0; i < numSamples - 1; i++) { - if (k && (ipid_diffs[i] > 5120 || ipid_diffs[i] % 256 != 0)) { + //on my x86_64 machine, I need a modulo 2 here, not 256 - as well for IPv4 as for IPv6 + if (k && (ipid_diffs[i] > 5120 || ipid_diffs[i] % 2 != 0)) { k = 0; } @@ -308,6 +310,7 @@ if (j == 1) return IPID_SEQ_INCR; + return IPID_SEQ_UNKNOWN; } @@ -2342,21 +2345,24 @@ } if (good_tcp_ipid_num >= 3) { - tcp_ipid_seqclass = get_ipid_sequence(good_tcp_ipid_num, hss->ipid.tcp_ipids, islocalhost(hss->target->TargetSockAddr())); + /* need to case to fit the changed paramters for ipids */ + tcp_ipid_seqclass = get_ipid_sequence(good_tcp_ipid_num, (long *) hss->ipid.tcp_ipids, islocalhost(hss->target->TargetSockAddr())); } else { tcp_ipid_seqclass = IPID_SEQ_UNKNOWN; } /* Only print open tcp ipid seqclass in the final report. */ hss->si.ipid_seqclass = tcp_ipid_seqclass; - if (good_tcp_closed_ipid_num >= 2) { - tcp_closed_ipid_seqclass = get_ipid_sequence(good_tcp_closed_ipid_num, hss->ipid.tcp_closed_ipids, islocalhost(hss->target->TargetSockAddr())); + if (good_tcp_closed_ipid_num >= 2) {\ + /* need to case to fit the changed paramters for ipids */ + tcp_closed_ipid_seqclass = get_ipid_sequence(good_tcp_closed_ipid_num, (long *) hss->ipid.tcp_closed_ipids, islocalhost(hss->target->TargetSockAddr())); } else { tcp_closed_ipid_seqclass = IPID_SEQ_UNKNOWN; } if (good_icmp_ipid_num >= 2) { - icmp_ipid_seqclass = get_ipid_sequence(good_icmp_ipid_num, hss->ipid.icmp_ipids, islocalhost(hss->target->TargetSockAddr())); + /* need to case to fit the changed paramters for ipids */ + icmp_ipid_seqclass = get_ipid_sequence(good_icmp_ipid_num, (long *) hss->ipid.icmp_ipids, islocalhost(hss->target->TargetSockAddr())); } else { icmp_ipid_seqclass = IPID_SEQ_UNKNOWN; } Index: osscan2.h =================================================================== --- osscan2.h (revision 30909) +++ osscan2.h (working copy) @@ -155,7 +155,8 @@ void os_scan2(std::vector &Targets); int get_initial_ttl_guess(u8 ttl); -int get_ipid_sequence(int numSamples, int *ipids, int islocalhost); +/* ipids is long to also store ipv6 ipids */ +int get_ipid_sequence(int numSamples, long *ipids, int islocalhost); /******************************************************************************