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 + -
显示快捷键?