scan_engine.cc
来自「Ubuntu packages of security software。 相」· CC 代码 · 共 1,755 行 · 第 1/5 页
CC
1,755 行
long tdiff; if (target->timedOut(&USI->now) || completed()) { if (when) *when = USI->now; return false; } if (rld.rld_waiting) { packTime = TIMEVAL_MSEC_SUBTRACT(rld.rld_waittime, USI->now); if (packTime <= 0) { if (when) *when = USI->now; return true; } if (when) *when = rld.rld_waittime; return false; } if (sdn.delayms) { packTime = TIMEVAL_MSEC_SUBTRACT(USI->now, lastprobe_sent); if (packTime < (int) sdn.delayms) { if (when) { TIMEVAL_MSEC_ADD(*when, lastprobe_sent, sdn.delayms); } return false; } } getTiming(&tmng); if (tmng.cwnd >= num_probes_active + .5 && (freshPortsLeft() || num_probes_waiting_retransmit || !retry_stack.empty())) { if (when) *when = USI->now; return true; } if (!when) return false; TIMEVAL_MSEC_ADD(earliest_to, USI->now, 10000); // Any timeouts coming up? for(probeI = probes_outstanding.begin(); probeI != probes_outstanding.end(); probeI++) { if (!(*probeI)->timedout) { TIMEVAL_MSEC_ADD(probe_to, (*probeI)->sent, probeTimeout() / 1000); if (TIMEVAL_SUBTRACT(probe_to, earliest_to) < 0) { earliest_to = probe_to; } } } // Will any scan delay affect this? if (sdn.delayms) { TIMEVAL_MSEC_ADD(sendTime, lastprobe_sent, sdn.delayms); if (TIMEVAL_MSEC_SUBTRACT(sendTime, USI->now) < 0) sendTime = USI->now; tdiff = TIMEVAL_MSEC_SUBTRACT(earliest_to, sendTime); /* Timeouts previous to the sendTime requirement are pointless, and those later than sendTime are not needed if we can send a new packet at sendTime */ if (tdiff < 0) { earliest_to = sendTime; } else { getTiming(&tmng); if (tdiff > 0 && tmng.cwnd > num_probes_active + .5) { earliest_to = sendTime; } } } *when = earliest_to; return false;}/* If there are pending probe timeouts, fills in when with the time of the earliest one and returns true. Otherwise returns false and puts now in when. */bool HostScanStats::nextTimeout(struct timeval *when) { struct timeval probe_to, earliest_to; list<UltraProbe *>::iterator probeI; bool firstgood = true; assert(when); memset(&probe_to, 0, sizeof(probe_to)); memset(&earliest_to, 0, sizeof(earliest_to)); for(probeI = probes_outstanding.begin(); probeI != probes_outstanding.end(); probeI++) { if (!(*probeI)->timedout) { TIMEVAL_ADD(probe_to, (*probeI)->sent, probeTimeout()); if (firstgood || TIMEVAL_SUBTRACT(probe_to, earliest_to) < 0) { earliest_to = probe_to; firstgood = false; } } } *when = (firstgood)? USI->now : earliest_to; return (firstgood)? false : true;} /* gives the maximum try number (try numbers start at zero and increments for each retransmission) that may be used, based on the scan type, observed network reliability, timing mode, etc. This may change during the scan based on network traffic. If capped is not null, it will be filled with true if the tryno is at its upper limit. That often calls for a warning to be issued, and marking of remaining timedout ports firewalled or whatever is appropriate. If mayincrease is non-NULL, it is set to whether the allowedTryno may increase again. If it is false, any probes which have reached the given limit may be dealth with. */unsigned int HostScanStats::allowedTryno(bool *capped, bool *mayincrease) { list<UltraProbe *>::iterator probeI; UltraProbe *probe = NULL; bool allfinished = true; unsigned int maxval = 0; /* TODO: This should perhaps differ by scan type. */ maxval = MAX(1, max_successful_tryno + 1); if (maxval > (unsigned int) USI->perf.tryno_cap) { if (capped) *capped = true; maxval = USI->perf.tryno_cap; tryno_mayincrease = false; /* It never exceeds the cap */ } else if (capped) *capped = false; /* Decide if the tryno can possibly increase. */ if (tryno_mayincrease && num_probes_active == 0 && freshPortsLeft() == 0) { /* If every outstanding probe is timedout and at maxval, then no further retransmits are neccessary. */ for(probeI = probes_outstanding.begin(); probeI != probes_outstanding.end(); probeI++) { probe = *probeI; assert(probe->timedout); if (!probe->retransmitted && !probe->isPing() && probe->tryno < maxval) { /* Needs at least one more retransmit. */ allfinished = false; break; } } if (allfinished) tryno_mayincrease = false; } if (mayincrease) *mayincrease = tryno_mayincrease; return maxval;}UltraScanInfo::UltraScanInfo() {}UltraScanInfo::~UltraScanInfo() { while(!incompleteHosts.empty()) { delete incompleteHosts.front(); incompleteHosts.pop_front(); } while(!completedHosts.empty()) { delete completedHosts.front(); completedHosts.pop_front(); } delete gstats; delete SPM; if (rawsd >= 0) { close(rawsd); rawsd = -1; } if (pd) { pcap_close(pd); pd = NULL; } if (ethsd) { ethsd = NULL; /* NO need to eth_close it due to caching */ }}/* Returns true if this scan is a "raw" scan. A raw scan is ont that requires a raw socket or ethernet handle to send, or a pcap sniffer to receive. Basically, any scan type except pure TCP connect scans are raw. */bool UltraScanInfo::isRawScan() { return scantype != CONNECT_SCAN && (tcp_scan || udp_scan || prot_scan || ping_scan_arp || (ping_scan && (ptech.rawicmpscan || ptech.rawtcpscan || ptech.rawudpscan || ptech.rawprotoscan)));} /* A circular buffer of the incompleteHosts. nextIncompleteHost() gives the next one. The first time it is called, it will give the first host in the list. If incompleteHosts is empty, returns NULL. */HostScanStats *UltraScanInfo::nextIncompleteHost() { HostScanStats *nxt; if (incompleteHosts.empty()) return NULL; nxt = *nextI; nextI++; if (nextI == incompleteHosts.end()) nextI = incompleteHosts.begin(); return nxt;}/* This is the function for tuning the major values that affect scan performance */static void init_perf_values(struct ultra_scan_performance_vars *perf) { memset(perf, 0, sizeof(*perf)); /* TODO: I should revisit these values for tuning. They should probably at least be affected by -T. */ perf->low_cwnd = MAX(o.min_parallelism, 1); perf->max_cwnd = o.max_parallelism? o.max_parallelism : 300; perf->group_initial_cwnd = box(o.min_parallelism, perf->max_cwnd, 10); perf->host_initial_cwnd = perf->group_initial_cwnd; perf->quick_incr = 1; /* The congestion window grows faster with more aggressive timing. */ if (o.timing_level < 4) perf->cc_incr = 1; else perf->cc_incr = 2; perf->cc_scale_max = 50; perf->initial_ccthresh = 75; perf->ping_magnifier = 3; perf->pingtime = 5000000; perf->group_drop_cwnd_divisor = 2.0; /* Change the amount that ccthresh drops based on the timing level. */ double ccthresh_divisor; if (o.timing_level <= 3) ccthresh_divisor = (3.0 / 2.0); else if (o.timing_level <= 4) ccthresh_divisor = (4.0 / 3.0); else ccthresh_divisor = (5.0 / 4.0); perf->group_drop_ccthresh_divisor = ccthresh_divisor; perf->host_drop_ccthresh_divisor = ccthresh_divisor; perf->tryno_cap = o.getMaxRetransmissions();}/* Order of initializations in this function CAN BE IMPORTANT, so be careful mucking with it. */void UltraScanInfo::Init(vector<Target *> &Targets, struct scan_lists *pts, stype scantp) { unsigned int targetno = 0; HostScanStats *hss; int num_timedout = 0; gettimeofday(&now, NULL); ports = pts; seqmask = get_random_u32(); scantype = scantp; SPM = new ScanProgressMeter(scantype2str(scantype)); tcp_scan = udp_scan = prot_scan = ping_scan = noresp_open_scan = false; ping_scan_arp = false; memset((char *) &ptech, 0, sizeof(ptech)); switch(scantype) { case FIN_SCAN: case XMAS_SCAN: case MAIMON_SCAN: case NULL_SCAN: noresp_open_scan = true; case ACK_SCAN: case CONNECT_SCAN: case SYN_SCAN: case WINDOW_SCAN: tcp_scan = true; break; case UDP_SCAN: noresp_open_scan = true; udp_scan = true; break; case IPPROT_SCAN: noresp_open_scan = true; prot_scan = true; break; case PING_SCAN: ping_scan = true; /* What kind of pings are we doing? */ if (o.pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS)) ptech.rawicmpscan = 1; if (o.pingtype & PINGTYPE_UDP) ptech.rawudpscan = 1; if (o.pingtype & PINGTYPE_TCP) { if (o.isr00t && o.af() == AF_INET) ptech.rawtcpscan = 1; else ptech.connecttcpscan = 1; } if (o.pingtype & PINGTYPE_PROTO) ptech.rawprotoscan = 1; if (o.pingtype & PINGTYPE_CONNECTTCP) ptech.connecttcpscan = 1; break; case PING_SCAN_ARP: ping_scan = true; ping_scan_arp = true; break; default: break; } init_perf_values(&perf); for(targetno = 0; targetno < Targets.size(); targetno++) { if (Targets[targetno]->timedOut(&now)) { num_timedout++; continue; } hss = new HostScanStats(Targets[targetno], this); incompleteHosts.push_back(hss); } numInitialTargets = Targets.size(); nextI = incompleteHosts.begin(); gstats = new GroupScanStats(this); /* Peeks at several elements in USI - careful of order */ gstats->num_hosts_timedout += num_timedout; pd = NULL; rawsd = -1; ethsd = NULL; /* See if we need an ethernet handle or raw socket. Basically, it's if we aren't doing a TCP connect scan, or if we're doing a ping scan that requires it. */ if (isRawScan()) { if (ping_scan_arp || ((o.sendpref & PACKET_SEND_ETH) && Targets[0]->ifType() == devt_ethernet)) { /* We'll send ethernet packets with dnet */ ethsd = eth_open_cached(Targets[0]->deviceName()); if (ethsd == NULL) fatal("dnet: Failed to open device %s", Targets[0]->deviceName()); rawsd = -1; } else { /* Initialize a raw socket */ if ((rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 ) pfatal("socket troubles in %s", __func__); /* We do not wan't to unblock the socket since we want to wait if kernel send buffers fill up rather than get ENOBUF, and we won't be receiving on the socket anyway unblock_socket(rawsd);*/ broadcast_socket(rawsd);#ifndef WIN32 sethdrinclude(rawsd); #endif ethsd = NULL; } }}/* Return the total number of probes that may be sent to each host. This never changes after initialization. */unsigned int UltraScanInfo::numProbesPerHost(){ unsigned int numprobes; if (tcp_scan) { numprobes = ports->tcp_count; } else if (udp_scan) { numprobes = ports->udp_count; } else if (prot_scan) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?