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 = &eth;    }    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 + -
显示快捷键?