traceroute.cc
来自「Ubuntu packages of security software。 相」· CC 代码 · 共 1,501 行 · 第 1/4 页
CC
1,501 行
scaninfo.scan_flags = TH_ACK; scaninfo.open_response = TH_RST; scaninfo.closed_response = TH_RST; } else if (port == IPPROTO_UDP) { scaninfo.initial_proto = IPPROTO_UDP; } else if (port == IPPROTO_ICMP) { scaninfo.initial_proto = IPPROTO_ICMP; scaninfo.icmp_type = ICMP_ECHO; } } return port;}/* finite state machine that reads all incoming packets * and attempts to match them with sent probes */inline boolTraceroute::readTraceResponses () { struct ip *ip = NULL; struct ip *ip2 = NULL; struct icmp *icmp = NULL; struct icmp *icmp2 = NULL; struct tcp_hdr *tcp = NULL; struct udp_hdr *udp = NULL; struct link_header linkhdr; unsigned int bytes; struct timeval rcvdtime; TraceProbe *tp = NULL; TraceGroup *tg = NULL; u16 sport; u32 ipaddr; /* Got to look into readip_pcap's timeout value, perhaps make it dynamic */ ip = (struct ip *) readip_pcap (pd, &bytes, 10000, &rcvdtime, &linkhdr); if (ip == NULL) return finished (); if ((unsigned) ip->ip_hl * 4 + 20 > bytes) return finished (); switch (ip->ip_p) { case IPPROTO_ICMP: icmp = (struct icmp *) ((char *) ip + 4 * ip->ip_hl); ipaddr = ip->ip_src.s_addr; sport = ntohs(icmp->icmp_id); /* Process ICMP replies that encapsulate our original probe */ if (icmp->icmp_type == ICMP_DEST_UNREACH || icmp->icmp_type == ICMP_TIME_EXCEEDED) { ip2 = (struct ip *) (((char *) ip) + 4 * ip->ip_hl + 8); if (ip2->ip_p == IPPROTO_TCP) { tcp = (struct tcp_hdr *) ((u8 *) ip2 + ip2->ip_hl * 4); sport = htons (tcp->th_sport); } else if (ip2->ip_p == IPPROTO_UDP) { udp = (struct udp_hdr *) ((u8 *) ip2 + ip2->ip_hl * 4); sport = htons (udp->uh_sport); } else if (ip2->ip_p == IPPROTO_ICMP) { icmp2 = (struct icmp *) ((char *) ip2 + 4 * ip2->ip_hl); sport = ntohs(icmp2->icmp_id); } else { sport = htons(ip2->ip_id); } ipaddr = ip2->ip_dst.s_addr; } if (TraceGroups.find (ipaddr) != TraceGroups.end ()) tg = TraceGroups[ipaddr]; else break; if (tg->TraceProbes.find (sport) != tg->TraceProbes.end ()) tp = tg->TraceProbes[sport]; else break; if (tp->ipreplysrc.s_addr) break; if ((tg->proto == IPPROTO_UDP && (ip2 && ip2->ip_p == IPPROTO_UDP)) || (icmp->icmp_type == ICMP_DEST_UNREACH)) { switch (icmp->icmp_code) { /* reply from a closed port */ case ICMP_PORT_UNREACH: /* replies from a filtered port */ case ICMP_HOST_UNREACH: case ICMP_PROT_UNREACH: case ICMP_NET_ANO: case ICMP_HOST_ANO: case ICMP_PKT_FILTERED: if (tp->probeType () == PROBE_TTL) { tg->setHopDistance (o.ttl - ip2->ip_ttl, 0); tg->start_ttl = tg->ttl = tg->hopDistance; } else { tg->gotReply = true; if (tg->start_ttl < tg->ttl) tg->ttl = tg->start_ttl + 1; } } } /* icmp ping scan replies */ else if (tg->proto == IPPROTO_ICMP && (icmp->icmp_type == ICMP_ECHOREPLY || icmp->icmp_type == ICMP_ADDRESSREPLY || icmp->icmp_type == ICMP_TIMESTAMPREPLY)) { if (tp->probeType () == PROBE_TTL) { tg->setHopDistance (get_initial_ttl_guess (ip->ip_ttl), ip->ip_ttl); tg->start_ttl = tg->ttl = tg->hopDistance; } else { tg->gotReply = true; if (tg->start_ttl < tg->ttl) tg->ttl = tg->start_ttl + 1; } } if (tp->timing.getState () == P_TIMEDOUT) tp->timing.setState (P_OK); else tg->decRemaining (); tg->repliedPackets++; tg->consecTimeouts = 0; tp->timing.adjustTimeouts (&rcvdtime, tg->scanDelay); tp->ipreplysrc.s_addr = ip->ip_src.s_addr; /* check to see if this hop is in the referece trace. If * it is then we stop tracing this target and assume * all subsequent hops match the common path */ if (commonPath[tp->ttl] == tp->ipreplysrc.s_addr && tp->ttl > 1 && tg->gotReply && tg->getState () != G_FINISH) { tg->setState (G_FINISH); tg->consolidation_start = tp->ttl+1; cp_flag = 1; break; } else if (commonPath[tp->ttl] == 0) { commonPath[tp->ttl] = tp->ipreplysrc.s_addr; /* remember which host is the reference trace */ if(!cp_flag) { ref_ipaddr.s_addr = tg->ipdst; cp_flag = 1; } } break; case IPPROTO_TCP: if ((unsigned) ip->ip_hl * 4 + 20 > bytes) break; tcp = (struct tcp_hdr *) ((char *) ip + 4 * ip->ip_hl); if (TraceGroups.find (ip->ip_src.s_addr) != TraceGroups.end ()) tg = TraceGroups[ip->ip_src.s_addr]; else break; if (tg->TraceProbes.find (htons (tcp->th_dport)) != tg->TraceProbes.end ()) tp = tg->TraceProbes[htons (tcp->th_dport)]; else break; /* already got the tcp packet for this group, * could be a left over rst or syn-ack */ if (tp->ipreplysrc.s_addr) break; /* We have reached the destination host and the * trace can stop for this target */ if (tcp->th_flags & scaninfo.open_response || tcp->th_flags & scaninfo.closed_response) { /* We might have got a late reply */ if (tp->timing.getState () == P_TIMEDOUT) tp->timing.setState (P_OK); else tg->decRemaining (); tp->timing.recvTime = rcvdtime; tp->ipreplysrc = ip->ip_src; tg->repliedPackets++; /* The probe was the reply from a ttl guess */ if (tp->probeType () == PROBE_TTL) { tg->setHopDistance (get_initial_ttl_guess (ip->ip_ttl), ip->ip_ttl); tg->start_ttl = tg->ttl = tg->hopDistance; } else { tg->gotReply = true; if (tg->start_ttl < tg->ttl) tg->ttl = tg->start_ttl + 1; } } break; case IPPROTO_UDP: if ((unsigned) ip->ip_hl * 4 + 8 > bytes) break; udp = (udp_hdr *) ((u8 *) ip + ip->ip_hl * 4); if (TraceGroups.find (ip->ip_src.s_addr) != TraceGroups.end ()) tg = TraceGroups[ip->ip_src.s_addr]; else break; if (tg->TraceProbes.find (htons (udp->uh_dport)) != tg->TraceProbes.end ()) tp = tg->TraceProbes[htons (udp->uh_dport)]; else break; if (tp->ipreplysrc.s_addr) break; /* We might have got a late reply */ if (tp->timing.getState () == P_TIMEDOUT) tp->timing.setState (P_OK); else tg->decRemaining (); tp->timing.recvTime = rcvdtime; tp->ipreplysrc.s_addr = ip->ip_src.s_addr; tg->repliedPackets++; if (tp->probeType () == PROBE_TTL) { tg->setHopDistance (get_initial_ttl_guess (ip->ip_ttl), ip->ip_ttl); tg->setState (G_OK); tg->start_ttl = tg->ttl = tg->hopDistance; } else { tg->gotReply = true; if (tg->start_ttl < tg->ttl) tg->ttl = tg->start_ttl + 1; } break; default: ; } return finished ();}/* Estimate how many hops away a host is by actively probing it. * * If the scan protocol isn't udp we guesstimate how many hops away * the target is by sending a probe to an open or closed port and * calculating a possible hop distance based on the returned ttl * * If the scan protocol is udp then we send a probe to a closed, * filtered or open port. Closed ports are more accurate because * we can exactly determine the hop distance based on the packet * return in the icmp port unreachable's payload. Open ports use * the same estimation method as tcp probes. Filtered ports are * only used as a last resort, although the hop distance guess is * accurate, the filtered response may not be from the destination * target, it may be from a node filtering the target */inline voidTraceroute::sendTTLProbes (vector < Target * >&Targets, vector < Target * >&valid_targets) { Target *t = NULL; long dport = 0; u16 sport = 0; u8 proto; TraceProbe *tp; TraceGroup *tg = NULL; vector < Target * >::iterator it = Targets.begin (); for (; it != Targets.end (); ++it) { t = *it; proto = scaninfo.initial_proto; /* No point in tracing directly connected nodes */ if (t->directlyConnected ()) continue; /* This node has already been sent a hop distance probe */ if (TraceGroups.find (t->v4hostip ()->s_addr) != TraceGroups.end ()) { valid_targets.push_back (t); continue; } /* Determine active port to probe */ if ((dport = getTracePort (proto, t)) == -1) { /* If we could not find a responsive tcp port then try * to find a responsive udp port */ if (o.udpscan && proto != IPPROTO_UDP) { proto = IPPROTO_UDP; dport = getTracePort (proto, t); } } if (dport == -1) { if (o.verbose > 1) log_write (LOG_STDOUT, "%s: no responsive %s\n", t->targetipstr (), o.ipprotscan ? "protocols" : "ports"); continue; } /* If this is a protocol scan getTracePort() returns * a protocol number for so we need a random destination * port */ if (o.ipprotscan) { proto = dport; dport = get_random_u16 (); scaninfo.initial_proto = IPPROTO_IP; } /* start off with a random source port and increment * it for each probes sent. The source port is the * distinguishing value used to identify each probe */ sport = get_random_u16 (); tg = new TraceGroup (t->v4hostip ()->s_addr, sport, dport, proto); tg->src_mac_addr = t->SrcMACAddress (); tg->nxt_mac_addr = t->NextHopMACAddress (); tg->sport++; TraceGroups[tg->ipdst] = tg; /* OS fingerprint engine may already have the distance so * we don't need to calculate it */ if (t->distance != -1) { tg->setHopDistance (0, t->distance); } else { tp = new TraceProbe (proto, t->v4hostip ()->s_addr, t->v4sourceip ()->s_addr, sport, dport); tp->setProbeType (PROBE_TTL); tp->ttl = o.ttl; tg->TraceProbes[sport] = tp; tg->incRemaining (); sendProbe (tp); } valid_targets.push_back (t); }}/* Send a single traceprobe object */intTraceroute::sendProbe (TraceProbe * tp) { u8 *tcpopts = NULL; int tcpoptslen = 0; u32 ack = 0; u8 *packet = NULL; u32 packetlen = 0; TraceGroup *tg = NULL; int decoy = 0; struct in_addr source; struct eth_nfo eth; struct eth_nfo *ethptr = NULL; if (scaninfo.scan_flags & TH_ACK) ack = rand (); if (scaninfo.scan_flags & TH_SYN) { tcpopts = (u8 *) "\x02\x04\x05\xb4"; tcpoptslen = 4; } if (TraceGroups.find (tp->ipdst.s_addr) == TraceGroups.end ()) return -1; tg = TraceGroups[tp->ipdst.s_addr]; /* required to send raw packets in windows */ if (ethsd) { memcpy (eth.srcmac, tg->src_mac_addr, 6); memcpy (eth.dstmac, tg->nxt_mac_addr, 6); eth.ethsd = ethsd; eth.devname[0] = '\0'; ethptr = ð } if (tg->TraceProbes.find (tp->sport) == tg->TraceProbes.end ()) { tg->nextTTL (); if (tg->ttl > MAX_TTL) { tg->setState (G_ALIVE_TTL); return -1; } if (!tg->ttl || tg->gotReply && tg->noDistProbe) { tg->setState (G_FINISH); return 0; } tg->sport++; tp->ttl = tg->ttl; tp->dport = tg->dport; tg->incRemaining (); } else { /* this probe is a retransmission */ tp->timing.setState (P_OK); } tg->TraceProbes[tp->sport] = tp; for (decoy = 0; decoy < o.numdecoys; decoy++) { enforce_scan_delay (&tp->timing.sendTime, tg->scanDelay);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?