idle_scan.cc
来自「Ubuntu packages of security software。 相」· CC 代码 · 共 1,063 行 · 第 1/3 页
CC
1,063 行
gettimeofday(&end, NULL); openports = -1; tries = 0; TIMEVAL_MSEC_ADD(probe_times[0], start, MAX(50, (target->to.srtt * 3/4) / 1000)); TIMEVAL_MSEC_ADD(probe_times[1], start, target->to.srtt / 1000 ); TIMEVAL_MSEC_ADD(probe_times[2], end, MAX(75, (2 * target->to.srtt + target->to.rttvar) / 1000)); TIMEVAL_MSEC_ADD(probe_times[3], end, MIN(4000, (2 * target->to.srtt + (target->to.rttvar << 2 )) / 1000)); do { if (tries == 2) dotry3 = (get_random_u8() > 200); if (tries == 3 && !dotry3) break; /* We usually want to skip the long-wait test */ if (tries == 3 || (tries == 2 && !dotry3)) lasttry = 1; gettimeofday(&now, NULL); sleeptime = TIMEVAL_SUBTRACT(probe_times[tries], now); if (!lasttry && proxyprobes_sent > 0 && sleeptime < 50000) continue; /* No point going again so soon */ if (tries == 0 && sleeptime < 500) sleeptime = 500; if (o.debugging > 1) error("In preparation for idle scan probe try #%d, sleeping for %d usecs", tries, sleeptime); if (sleeptime > 0) usleep(sleeptime); newipid = ipid_proxy_probe(proxy, &sent, &rcvd); proxyprobes_sent += sent; proxyprobes_rcvd += rcvd; if (newipid > 0) { ipid_dist = ipid_distance(proxy->seqclass, proxy->latestid, newipid); /* I used to only do this if ipid_sit >= proxyprobes_sent, but I'd rather have a negative number in that case */ if (ipid_dist < proxyprobes_sent) { if (o.debugging) error("%s: Must have lost a sent packet because ipid_dist is %d while proxyprobes_sent is %d.", __func__, ipid_dist, proxyprobes_sent); /* I no longer whack timing here ... done at bottom */ } ipid_dist -= proxyprobes_sent; if (ipid_dist > openports) { openports = ipid_dist; gettimeofday(&latestchange, NULL); } else if (ipid_dist < openports && ipid_dist >= 0) { /* Uh-oh. Perhaps I dropped a packet this time */ if (o.debugging > 1) { error("%s: Counted %d open ports in try #%d, but counted %d earlier ... probably a proxy_probe problem", __func__, ipid_dist, tries, openports); } /* I no longer whack timing here ... done at bottom */ } } if (openports > numports || (numports <= 2 && (openports == numports))) break; } while(tries++ < 3); if (proxyprobes_sent > proxyprobes_rcvd) { /* Uh-oh. It looks like we lost at least one proxy probe packet */ if (o.debugging) { error("%s: Sent %d probes; only %d responses. Slowing scan.", __func__, proxyprobes_sent, proxyprobes_rcvd); } proxy->senddelay += 5000; proxy->senddelay = MIN(proxy->max_senddelay, proxy->senddelay); /* No group size should be greater than .5s of send delays */ proxy->current_groupsz = MAX(proxy->min_groupsz, MIN(proxy->current_groupsz, 500000 / (proxy->senddelay+1))); } else { /* Yeah, we got as many responses as we sent probes. This calls for a very light timing acceleration ... */ proxy->senddelay = (int) (proxy->senddelay * 0.95); if (proxy->senddelay < 500) proxy->senddelay = 0; proxy->current_groupsz = MAX(proxy->min_groupsz, MIN(proxy->current_groupsz, 500000 / (proxy->senddelay+1))); } if ((openports > 0) && (openports <= numports)) { /* Yeah, we found open ports... lets adjust the timing ... */ if (o.debugging > 2) error("%s: found %d open ports (out of %d) in %lu usecs", __func__, openports, numports, (unsigned long) TIMEVAL_SUBTRACT(latestchange, start)); if (sent_time) *sent_time = start; if (rcv_time) *rcv_time = latestchange; } if (newipid > 0) proxy->latestid = newipid; if (eth.ethsd) { eth.ethsd = NULL; } /* don't need to close it due to caching */ return openports;}/* The job of this function is to use the idle scan technique to count the number of open ports in the given list. Under the covers, this function just farms out the hard work to another function */static int idlescan_countopen(struct idle_proxy_info *proxy, Target *target, u16 *ports, int numports, struct timeval *sent_time, struct timeval *rcv_time) { int tries = 0; int openports; do { openports = idlescan_countopen2(proxy, target, ports, numports, sent_time, rcv_time); tries++; if (tries == 6 || (openports >= 0 && openports <= numports)) break; if (o.debugging) { error("%s: In try #%d, counted %d open ports out of %d. Retrying", __func__, tries, openports, numports); } /* Sleep for a little while -- maybe proxy host had brief birst of traffic or similar problem */ sleep(tries * tries); if (tries == 5) sleep(45); /* We're gonna give up if this fails, so we will be a bit patient */ /* Since the host may have received packets while we were sleeping, lets update our proxy IP ID counter */ proxy->latestid = ipid_proxy_probe(proxy, NULL, NULL); } while(1); if (openports < 0 || openports > numports ) { /* Oh f*ck!!!! */ fatal("Idle scan is unable to obtain meaningful results from proxy %s (%s). I'm sorry it didn't work out.", proxy->host.HostName(), proxy->host.targetipstr()); } if (o.debugging > 2) error("%s: %d ports found open out of %d, starting with %hu", __func__, openports, numports, ports[0]); return openports;}/* Recursively idle scans scans a group of ports using a depth-first divide-and-conquer strategy to find the open one(s) */static int idle_treescan(struct idle_proxy_info *proxy, Target *target, u16 *ports, int numports, int expectedopen) { int firstHalfSz = (numports + 1)/2; int secondHalfSz = numports - firstHalfSz; int flatcount1, flatcount2; int deepcount1 = -1, deepcount2 = -1; struct timeval sentTime1, rcvTime1, sentTime2, rcvTime2; int retrycount = -1, retry2 = -1; int totalfound = 0; /* Scan the first half of the range */ if (o.debugging > 1) { error("%s: Called against %s with %d ports, starting with %hu. expectedopen: %d", __func__, target->targetipstr(), numports, ports[0], expectedopen); error("IDLE SCAN TIMING: grpsz: %.3f delay: %d srtt: %d rttvar: %d", proxy->current_groupsz, proxy->senddelay, target->to.srtt, target->to.rttvar); } 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); /* Now we assume deepcount1 is right, and adjust timing if flatcount1 was wrong */ adjust_idle_timing(proxy, target, flatcount1, deepcount1); } /* I guess we had better do the second half too ... */ flatcount2 = idlescan_countopen(proxy, target, ports + firstHalfSz, secondHalfSz, &sentTime2, &rcvTime2); if ((secondHalfSz) > 1 && flatcount2 > 0) { /* A port appears open! We dig down deeper to find it ... */ deepcount2 = idle_treescan(proxy, target, ports + firstHalfSz, secondHalfSz, flatcount2); /* Now we assume deepcount1 is right, and adjust timing if flatcount1 was wrong */ adjust_idle_timing(proxy, target, flatcount2, deepcount2); } totalfound = (deepcount1 == -1)? flatcount1 : deepcount1; totalfound += (deepcount2 == -1)? flatcount2 : deepcount2; if ((flatcount1 + flatcount2 == totalfound) && (expectedopen == totalfound || expectedopen == -1)) { if (flatcount1 > 0) { if (o.debugging > 1) { error("Adjusting timing -- idlescan_countopen correctly found %d open ports (out of %d, starting with %hu)", flatcount1, firstHalfSz, ports[0]); } adjust_timeouts2(&sentTime1, &rcvTime1, &(target->to)); } if (flatcount2 > 0) { if (o.debugging > 2) { error("Adjusting timing -- idlescan_countopen correctly found %d open ports (out of %d, starting with %hu)", flatcount2, secondHalfSz, ports[firstHalfSz]); } adjust_timeouts2(&sentTime2, &rcvTime2, &(target->to)); } } if (totalfound != expectedopen) { if (deepcount1 == -1) { retrycount = idlescan_countopen(proxy, target, ports, firstHalfSz, NULL, NULL); if (retrycount != flatcount1) { /* We have to do a deep count if new ports were found and there are more than 1 total */ if (firstHalfSz > 1 && retrycount > 0) { retry2 = retrycount; retrycount = idle_treescan(proxy, target, ports, firstHalfSz, retrycount); adjust_idle_timing(proxy, target, retry2, retrycount); } else { if (o.debugging) error("Adjusting timing because my first scan of %d ports, starting with %hu found %d open, while second scan yielded %d", firstHalfSz, ports[0], flatcount1, retrycount); adjust_idle_timing(proxy, target, flatcount1, retrycount); } totalfound += retrycount - flatcount1; flatcount1 = retrycount; /* If our first count erroneously found and added an open port, we must delete it */ if (firstHalfSz == 1 && flatcount1 == 1 && retrycount == 0) target->ports.removePort(ports[0], IPPROTO_TCP); } } if (deepcount2 == -1) { retrycount = idlescan_countopen(proxy, target, ports + firstHalfSz, secondHalfSz, NULL, NULL); if (retrycount != flatcount2) { if (secondHalfSz > 1 && retrycount > 0) { retry2 = retrycount; retrycount = idle_treescan(proxy, target, ports + firstHalfSz, secondHalfSz, retrycount); adjust_idle_timing(proxy, target, retry2, retrycount); } else { if (o.debugging) error("Adjusting timing because my first scan of %d ports, starting with %hu found %d open, while second scan yeilded %d", secondHalfSz, ports[firstHalfSz], flatcount2, retrycount); adjust_idle_timing(proxy, target, flatcount2, retrycount); } totalfound += retrycount - flatcount2; flatcount2 = retrycount; /* If our first count erroneously found and added an open port, we must delete it */ if (secondHalfSz == 1 && flatcount2 == 1 && retrycount == 0) target->ports.removePort(ports[firstHalfSz], IPPROTO_TCP); } } } if (firstHalfSz == 1 && flatcount1 == 1) target->ports.addPort(ports[0], IPPROTO_TCP, NULL, PORT_OPEN); if ((secondHalfSz == 1) && flatcount2 == 1) target->ports.addPort(ports[firstHalfSz], IPPROTO_TCP, NULL, PORT_OPEN); return totalfound;}/* 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 */void idle_scan(Target *target, u16 *portarray, int numports, char *proxyName) { static char lastproxy[MAXHOSTNAMELEN + 1] = ""; /* The proxy used in any previous call */ static struct idle_proxy_info proxy; int groupsz; int portidx = 0; /* Used for splitting the port array into chunks */ int portsleft; time_t starttime; char scanname[32]; Snprintf(scanname, sizeof(scanname), "idle scan against %s", target->NameIP()); ScanProgressMeter SPM(scanname); if (numports == 0) return; /* nothing to scan for */ if (!proxyName) fatal("idle scan requires a proxy host"); if (*lastproxy && strcmp(proxyName, lastproxy)) fatal("%s: You are not allowed to change proxies midstream. Sorry", __func__); assert(target); if (target->timedOut(NULL)) return; if (target->ifType() == devt_loopback) { log_write(LOG_STDOUT, "Skipping Idle Scan against %s -- you can't idle scan your own machine (localhost).\n", target->NameIP()); return; } target->startTimeOutClock(NULL); /* If this is the first call, */ if (!*lastproxy) { initialize_idleproxy(&proxy, proxyName, target->v4hostip()); } starttime = time(NULL); /* If we don't have timing infoz for the new target, we'll use values derived from the proxy */ if (target->to.srtt == -1 && target->to.rttvar == -1) { target->to.srtt = MAX(200000,2 * proxy.host.to.srtt); target->to.rttvar = MAX(10000, MIN(proxy.host.to.rttvar, 2000000)); target->to.timeout = target->to.srtt + (target->to.rttvar << 2); } else { target->to.srtt = MAX(target->to.srtt, proxy.host.to.srtt); target->to.rttvar = MAX(target->to.rttvar, proxy.host.to.rttvar); target->to.timeout = target->to.srtt + (target->to.rttvar << 2); } /* Now I guess it is time to let the scanning begin! Since Idle scan is sort of tree structured (we scan a group and then divide it up and drill down in subscans of the group), we split the port space into smaller groups and then call a recursive divide-and-counquer function to find the open ports */ while(portidx < numports) { portsleft = numports - portidx; /* current_groupsz is doubled below because idle_subscan cuts in half */ groupsz = MIN(portsleft, (int) (proxy.current_groupsz * 2)); idle_treescan(&proxy, target, portarray + portidx, groupsz, -1); portidx += groupsz; } char additional_info[14]; Snprintf(additional_info, sizeof(additional_info), "%d ports", numports); SPM.endTask(NULL, additional_info); /* Now we go through the ports which were not determined were scanned but not determined to be open, and add them in the "closed" state */ for(portidx = 0; portidx < numports; portidx++) { if (target->ports.getPortEntry(portarray[portidx], IPPROTO_TCP) == NULL) { target->ports.addPort(portarray[portidx], IPPROTO_TCP, NULL, PORT_CLOSEDFILTERED); target->ports.setStateReason(portarray[portidx], IPPROTO_TCP, ER_NOIPIDCHANGE, 0, 0); } else target->ports.setStateReason(portarray[portidx], IPPROTO_TCP, ER_IPIDCHANGE, 0, 0); } target->stopTimeOutClock(NULL); return;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?