From ccce12128fb7249f4625451dd2c6bdfc2e093a96 Mon Sep 17 00:00:00 2001 From: fyodor Date: Sat, 31 Dec 2005 00:32:42 +0000 Subject: [PATCH] Just added Paul's status patch --- CHANGELOG | 14 ++++++++++++- Makefile.in | 8 ++++---- NmapOps.h | 7 +++++++ docs/nmap.1 | 13 ++++++++---- docs/nmap.usage.txt | 2 +- global_structures.h | 2 +- mswin32/nmap.vcproj | 6 ++++++ nmap.cc | 49 ++++++++++++++++++++++++++++++--------------- osscan.cc | 8 ++++++++ output.cc | 31 +++++++++++++++++++--------- output.h | 6 ++++-- scan_engine.cc | 44 +++++++++++++++++++++++++++++++++++++++- service_scan.cc | 19 ++++++++++++++++++ targets.cc | 3 +++ timing.cc | 38 ++++++++++++++++++++++++++++++----- timing.h | 5 ++++- 16 files changed, 209 insertions(+), 46 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2c301ad59..3d70e14d3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,16 @@ -# Nmap Changelog ($Id$) +# Nmap Changelog ($Id$); -*-text-*- +UNRELEASED + +o Added real time status reporting, as documented at + http://www.insecure.org/nmap/man/man-runtime-interaction.html . + While Nmap is running, you can now press 'v' to increase verbosity, + 'd' to increase the debugging level, 'p' to enable packet tracing, + or the capital versions (V,D,P) to do the opposite. Any other key + (such as enter) will print out a status message giving the estimated + time until scan completion. This only works on UNIX for now. Do we + have any volunteers to add Windows support? This feature was + created by Paul Tarjan (ptarjan(a)stanford.edu) as part of the + Google Summer of Code. 3.96BETA1 diff --git a/Makefile.in b/Makefile.in index d597a6d2f..a2f91c284 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -export NMAP_VERSION = 3.96BETA1 +export NMAP_VERSION = 3.96BETA2 NMAP_NAME= Nmap NMAP_URL= http://www.insecure.org/nmap/ NMAP_PLATFORM=@host@ @@ -46,11 +46,11 @@ TARGET = nmap TARGETNMAPFE=@TARGETNMAPFE@ INSTALLNMAPFE=@INSTALLNMAPFE@ -export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc @COMPAT_SRCS@ +export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc tty.cc @COMPAT_SRCS@ -OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o @COMPAT_OBJS@ +OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o tty.o @COMPAT_OBJS@ -export DEPS = nmap.h nmap_amigaos.h nmap_error.h targets.h idle_scan.h osscan.h output.h scan_engine.h timing.h tcpip.h utils.h global_structures.h charpool.h services.h protocols.h nmap_rpc.h portlist.h NmapOps.h TargetGroup.h Target.h FingerPrintResults.h service_scan.h NmapOutputTable.h MACLookup.h +export DEPS = nmap.h nmap_amigaos.h nmap_error.h targets.h idle_scan.h osscan.h output.h scan_engine.h timing.h tcpip.h utils.h global_structures.h charpool.h services.h protocols.h nmap_rpc.h portlist.h NmapOps.h TargetGroup.h Target.h FingerPrintResults.h service_scan.h NmapOutputTable.h MACLookup.h tty.h # %.o : %.cc -- nope this is a GNU extension diff --git a/NmapOps.h b/NmapOps.h index 01f65fe9d..6b50f7677 100644 --- a/NmapOps.h +++ b/NmapOps.h @@ -282,6 +282,13 @@ class NmapOps { FILE *nmap_stdout; /* Nmap standard output */ int ttl; // Time to live char *datadir; + + // Statistics Options set in nmap.cc + int numhosts_scanned; + int numhosts_up; + int numhosts_scanning; + stype scantype; + private: int max_rtt_timeout; int min_rtt_timeout; diff --git a/docs/nmap.1 b/docs/nmap.1 index 8b4d87093..2e1a60067 100644 --- a/docs/nmap.1 +++ b/docs/nmap.1 @@ -2,7 +2,7 @@ .\" It was generated using the DocBook XSL Stylesheets (version 1.69.1). .\" Instead of manually editing it, you probably should edit the DocBook XML .\" source for it and then use the DocBook XSL Stylesheets to regenerate it. -.TH "NMAP" "1" "12/29/2005" "" "Nmap Reference Guide" +.TH "NMAP" "1" "12/30/2005" "" "Nmap Reference Guide" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) @@ -1233,9 +1233,14 @@ Prints the Nmap version number and exits. \fB\-h\fR; \fB\-\-help\fR (Print help summary page) Prints a short help screen with the most common command flags. Running Nmap without any arguments does the same thing. .SH "RUNTIME INTERACTION" -.PP -This feature does not yet exist in Nmap. I need to either add it or remove this section -.PP +.sp +.it 1 an-trap +.nr an-no-space-flag 1 +.nr an-break-flag 1 +.br +\fBNote\fR +The runtime interaction feature is not yet + supported on Windows..PP During the execution of nmap, all key presses are captured. This allows you to interact with the program without aborting and restarting it. Certain special keys will change options, while any other keys will print out a status message telling you about the scan. The convention is that \fIlowercase letters increase\fR the amount of printing, and diff --git a/docs/nmap.usage.txt b/docs/nmap.usage.txt index fd67b879a..ee695d6ea 100644 --- a/docs/nmap.usage.txt +++ b/docs/nmap.usage.txt @@ -1,4 +1,4 @@ -Nmap 3.96BETA1 ( http://www.insecure.org/nmap/ ) +Nmap 3.96BETA2 ( http://www.insecure.org/nmap/ ) Usage: nmap [Scan Type(s)] [Options] {target specification} TARGET SPECIFICATION: Can pass hostnames, IP addresses, networks, etc. diff --git a/global_structures.h b/global_structures.h index 6c8be39da..bc7bdefb3 100644 --- a/global_structures.h +++ b/global_structures.h @@ -228,6 +228,6 @@ struct scan_lists { int prot_count; }; -typedef enum { ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP} stype; +typedef enum { ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN} stype; #endif /*GLOBAL_STRUCTURES_H */ diff --git a/mswin32/nmap.vcproj b/mswin32/nmap.vcproj index 52829eea2..a2d3f30da 100644 --- a/mswin32/nmap.vcproj +++ b/mswin32/nmap.vcproj @@ -212,6 +212,9 @@ + + @@ -301,6 +304,9 @@ + + diff --git a/nmap.cc b/nmap.cc index c5accc327..b17055bc5 100644 --- a/nmap.cc +++ b/nmap.cc @@ -107,6 +107,7 @@ #include "timing.h" #include "NmapOps.h" #include "MACLookup.h" +#include "tty.h" #ifdef WIN32 #include "winfix.h" #endif @@ -205,15 +206,12 @@ int nmap_main(int argc, char *argv[]) { char *host_spec = NULL, *exclude_spec = NULL; short fastscan=0, randomize=1, resolve_all=0; short quashargv = 0; - int numhosts_scanned = 0; char **host_exp_group; char *idleProxy = NULL; /* The idle host used to "Proxy" an Idlescan */ int num_host_exp_groups = 0; char *machinefilename = NULL, *kiddiefilename = NULL, *normalfilename = NULL, *xmlfilename = NULL; HostGroupState *hstate = NULL; - int numhosts_up = 0; - int starttime; char *endptr = NULL; struct scan_lists *ports = NULL; TargetGroup *exclude_group = NULL; @@ -775,6 +773,8 @@ int nmap_main(int argc, char *argv[]) { win_init(); #endif + tty_init(); // Put the keyboard in raw mode + #if HAVE_SIGNAL if (!o.debugging) signal(SIGSEGV, sigdie); @@ -1034,8 +1034,6 @@ int nmap_main(int argc, char *argv[]) { shortfry(ports->prots, ports->prot_count); } - starttime = time(NULL); - /* Time to create a hostgroup state object filled with all the requested machines */ host_exp_group = (char **) safe_malloc(o.ping_group_sz * sizeof(char *)); @@ -1057,7 +1055,7 @@ int nmap_main(int argc, char *argv[]) { (host_spec = grab_next_host_spec(inputfd, argc, fakeargv))) { host_exp_group[num_host_exp_groups++] = strdup(host_spec); // For purposes of random scan - if (o.max_ips_to_scan && o.max_ips_to_scan <= numhosts_scanned + num_host_exp_groups) + if (o.max_ips_to_scan && o.max_ips_to_scan <= o.numhosts_scanned + num_host_exp_groups) break; } @@ -1067,7 +1065,7 @@ int nmap_main(int argc, char *argv[]) { host_exp_group, num_host_exp_groups); do { - ideal_scan_group_sz = determineScanGroupSize(numhosts_scanned, ports); + ideal_scan_group_sz = determineScanGroupSize(o.numhosts_scanned, ports); while(Targets.size() < ideal_scan_group_sz) { currenths = nexthost(hstate, exclude_group, ports, &(o.pingtype)); if (!currenths) { @@ -1078,7 +1076,7 @@ int nmap_main(int argc, char *argv[]) { num_host_exp_groups = 0; /* Now grab any new expressions */ while(num_host_exp_groups < o.ping_group_sz && - (!o.max_ips_to_scan || o.max_ips_to_scan > numhosts_scanned + num_host_exp_groups) && + (!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned + num_host_exp_groups) && (host_spec = grab_next_host_spec(inputfd, argc, fakeargv))) { // For purposes of random scan host_exp_group[num_host_exp_groups++] = strdup(host_spec); @@ -1094,10 +1092,10 @@ int nmap_main(int argc, char *argv[]) { if (!currenths) break; } - numhosts_scanned++; + o.numhosts_scanned++; if (currenths->flags & HOST_UP && !o.listscan) - numhosts_up++; + o.numhosts_up++; /* Lookup the IP */ if (((currenths->flags & HOST_UP) || resolve_all) && !o.noresolve) { @@ -1162,7 +1160,7 @@ int nmap_main(int argc, char *argv[]) { if (Targets.size() > 0 && strcmp(Targets[Targets.size() - 1]->deviceName(), currenths->deviceName())) { returnhost(hstate); - numhosts_scanned--; numhosts_up--; + o.numhosts_scanned--; o.numhosts_up--; break; } o.decoys[o.decoyturn] = currenths->v4source(); @@ -1173,12 +1171,17 @@ int nmap_main(int argc, char *argv[]) { if (Targets.size() == 0) break; /* Couldn't find any more targets */ + // Set the variable for status printing + o.numhosts_scanning = Targets.size(); + // Our source must be set in decoy list because nexthost() call can // change it (that issue really should be fixed when possible) if (o.af() == AF_INET && o.RawScan()) o.decoys[o.decoyturn] = Targets[0]->v4source(); /* I now have the group for scanning in the Targets vector */ + + // Ultra_scan sets o.scantype for us so we don't have to worry if (o.synscan) ultra_scan(Targets, ports, SYN_SCAN); @@ -1212,17 +1215,26 @@ int nmap_main(int argc, char *argv[]) { /* These lame functions can only handle one target at a time */ for(targetno = 0; targetno < Targets.size(); targetno++) { currenths = Targets[targetno]; - if (o.idlescan) idle_scan(currenths, ports->tcp_ports, + if (o.idlescan) { + o.scantype = IDLE_SCAN; + keyWasPressed(); // Check if a status message should be printed + idle_scan(currenths, ports->tcp_ports, ports->tcp_count, idleProxy); + } if (o.bouncescan) { + o.scantype = BOUNCE_SCAN; + keyWasPressed(); // Check if a status message should be printed if (ftp.sd <= 0) ftp_anon_connect(&ftp); if (ftp.sd > 0) bounce_scan(currenths, ports->tcp_ports, ports->tcp_count, &ftp); } } - if (o.servicescan) + if (o.servicescan) { + o.scantype = SERVICE_SCAN; + keyWasPressed(); // Check if a status message should be printed service_scan(Targets); + } for(targetno = 0; targetno < Targets.size(); targetno++) { currenths = Targets[targetno]; @@ -1234,8 +1246,9 @@ int nmap_main(int argc, char *argv[]) { if (o.servicescan || o.rpcscan) pos_scan(currenths, NULL, 0, RPC_SCAN); // Should be host parallelized. Though rarely takes a huge amt. of time. - if (o.osscan) + if (o.osscan) { os_scan(currenths); + } /* Now I can do the output and such for each host */ log_write(LOG_XML, ""); @@ -1266,7 +1279,7 @@ int nmap_main(int argc, char *argv[]) { delete currenths; Targets.pop_back(); } - } while(!o.max_ips_to_scan || o.max_ips_to_scan > numhosts_scanned); + } while(!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned); delete hstate; if (exclude_group) @@ -1280,7 +1293,7 @@ int nmap_main(int argc, char *argv[]) { num_host_exp_groups = 0; free(host_exp_group); - printfinaloutput(numhosts_scanned, numhosts_up, starttime); + printfinaloutput(); if (ports) { free(ports->tcp_ports); @@ -1932,6 +1945,10 @@ char *scantype2str(stype scantype) { case IPPROT_SCAN: return "IPProto Scan"; break; case PING_SCAN: return "Ping Scan"; break; case PING_SCAN_ARP: return "ARP Ping Scan"; break; + case IDLE_SCAN: return "Idle Scan"; break; + case BOUNCE_SCAN: return "Bounce Scan"; break; + case SERVICE_SCAN: return "Service Scan"; break; + case OS_SCAN: return "OS Scan"; break; default: assert(0); break; } diff --git a/osscan.cc b/osscan.cc index 08d4984dd..efbbf13ca 100644 --- a/osscan.cc +++ b/osscan.cc @@ -104,6 +104,7 @@ #include "osscan.h" #include "timing.h" #include "NmapOps.h" +#include "tty.h" #if TIME_WITH_SYS_TIME # include @@ -1280,6 +1281,8 @@ int bestaccidx; if (target->timedOut(NULL)) return 1; +o.scantype = OS_SCAN; + #ifdef WIN32 if (target->ifType() == devt_loopback) { log_write(LOG_STDOUT, "Skipping OS Scan against %s because it doesn't work against your own machine (localhost)\n", target->NameIP()); @@ -1313,6 +1316,11 @@ int bestaccidx; if (target->timedOut(&now)) return 1; + // Check if a status message is requested + if (keyWasPressed()) { + // Do nothing because the keyWasPressed Method prints out the basic status line + } + target->FPR->FPs[itry] = get_fingerprint(target, &si[itry]); match_fingerprint(target->FPR->FPs[itry], &FP_matches[itry], diff --git a/output.cc b/output.cc index 2f17a8acc..868922b25 100644 --- a/output.cc +++ b/output.cc @@ -1376,27 +1376,38 @@ void printserviceinfooutput(Target *currenths) { log_flush_all(); } +/* Prints a status message while the program is running */ +void printStatusMessage() { + // Pre-computations + struct timeval tv; + gettimeofday(&tv, NULL); + int time = (int) (o.TimeSinceStartMS(&tv) / 1000.0); + + log_write(LOG_STDOUT, + "Stats: %d:%02d:%02d elapsed; %d hosts completed (%d up), %d undergoing %s\n", + time/60/24, time/60 % 24, time % 60, o.numhosts_scanned, + o.numhosts_up, o.numhosts_scanning, scantype2str(o.scantype)); +} + /* Prints the statistics and other information that goes at the very end of an Nmap run */ -void printfinaloutput(int numhosts_scanned, int numhosts_up, - time_t starttime) { +void printfinaloutput() { time_t timep; - int i; char mytime[128]; struct timeval tv; char statbuf[128]; + gettimeofday(&tv, NULL); timep = time(NULL); - i = timep - starttime; - if (numhosts_scanned == 0) + if (o.numhosts_scanned == 0) fprintf(stderr, "WARNING: No targets were specified, so 0 hosts scanned.\n"); - if (numhosts_scanned == 1 && numhosts_up == 0 && !o.listscan && + if (o.numhosts_scanned == 1 && o.numhosts_up == 0 && !o.listscan && o.pingtype != PINGTYPE_NONE) log_write(LOG_STDOUT, "Note: Host seems down. If it is really up, but blocking our ping probes, try -P0\n"); /* log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\n"); */ - log_write(LOG_STDOUT|LOG_SKID, "Nmap finished: %d %s (%d %s up) scanned in %.3f seconds\n", numhosts_scanned, (numhosts_scanned == 1)? "IP address" : "IP addresses", numhosts_up, (numhosts_up == 1)? "host" : "hosts", o.TimeSinceStartMS(&tv) / 1000.0); + log_write(LOG_STDOUT|LOG_SKID, "Nmap finished: %d %s (%d %s up) scanned in %.3f seconds\n", o.numhosts_scanned, (o.numhosts_scanned == 1)? "IP address" : "IP addresses", o.numhosts_up, (o.numhosts_up == 1)? "host" : "hosts", o.TimeSinceStartMS(&tv) / 1000.0); if (o.verbose && o.isr00t && o.RawScan()) log_write(LOG_STDOUT|LOG_SKID, " %s\n", getFinalPacketStats(statbuf, sizeof(statbuf))); @@ -1404,10 +1415,10 @@ void printfinaloutput(int numhosts_scanned, int numhosts_up, Strncpy(mytime, ctime(&timep), sizeof(mytime)); chomp(mytime); - log_write(LOG_XML, "\n", (unsigned long) timep, mytime, numhosts_up, numhosts_scanned - numhosts_up, numhosts_scanned); + log_write(LOG_XML, "\n", (unsigned long) timep, mytime, o.numhosts_up, o.numhosts_scanned - o.numhosts_up, o.numhosts_scanned); - log_write(LOG_XML, "\n", mytime, numhosts_scanned, (numhosts_scanned == 1)? "IP address" : "IP addresses", numhosts_up, (numhosts_up == 1)? "host" : "hosts", o.TimeSinceStartMS(&tv) / 1000.0 ); - log_write(LOG_NORMAL|LOG_MACHINE, "# Nmap run completed at %s -- %d %s (%d %s up) scanned in %.3f seconds\n", mytime, numhosts_scanned, (numhosts_scanned == 1)? "IP address" : "IP addresses", numhosts_up, (numhosts_up == 1)? "host" : "hosts", o.TimeSinceStartMS(&tv) / 1000.0 ); + log_write(LOG_XML, "\n", mytime, o.numhosts_scanned, (o.numhosts_scanned == 1)? "IP address" : "IP addresses", o.numhosts_up, (o.numhosts_up == 1)? "host" : "hosts", o.TimeSinceStartMS(&tv) / 1000.0 ); + log_write(LOG_NORMAL|LOG_MACHINE, "# Nmap run completed at %s -- %d %s (%d %s up) scanned in %.3f seconds\n", mytime, o.numhosts_scanned, (o.numhosts_scanned == 1)? "IP address" : "IP addresses", o.numhosts_up, (o.numhosts_up == 1)? "host" : "hosts", o.TimeSinceStartMS(&tv) / 1000.0 ); log_write(LOG_XML, "\n"); log_flush_all(); diff --git a/output.h b/output.h index 4f2cc0d76..39e69e060 100644 --- a/output.h +++ b/output.h @@ -199,10 +199,12 @@ void printserviceinfooutput(Target *currenths); normal/skiddy/stdout output */ int print_iflist(void); +/* Prints a status message while the program is running */ +void printStatusMessage(); + /* Prints the statistics and other information that goes at the very end of an Nmap run */ -void printfinaloutput(int numhosts_scanned, int numhosts_up, - time_t starttime); +void printfinaloutput(); char* xml_convert (const char* str); #endif /* OUTPUT_H */ diff --git a/scan_engine.cc b/scan_engine.cc index 62e0270bd..4254e0f59 100644 --- a/scan_engine.cc +++ b/scan_engine.cc @@ -105,9 +105,11 @@ #include "scan_engine.h" #include "timing.h" #include "NmapOps.h" +#include "tty.h" #include #include + using namespace std; extern NmapOps o; class UltraScanInfo; @@ -2404,7 +2406,7 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) { /* Print occasional remaining time estimates, as well as debugging information */ -static void printAnyStats(UltraScanInfo *USI) { +void printAnyStats(UltraScanInfo *USI) { list::iterator hostI; HostScanStats *hss; @@ -3333,6 +3335,7 @@ void ultra_scan(vector &Targets, struct scan_lists *ports, stype scantype) { UltraScanInfo *USI = NULL; time_t starttime; + o.scantype = scantype; if (Targets.size() == 0) { return; @@ -3375,6 +3378,34 @@ void ultra_scan(vector &Targets, struct scan_lists *ports, gettimeofday(&USI->now, NULL); // printf("TRACE: Finished waitForResponses() at %.4fs\n", o.TimeSinceStartMS(&USI->now) / 1000.0); processData(USI); + + if (keyWasPressed()) { + /* Get the Completion percent */ + + list::iterator hostI; + HostScanStats *host = NULL; + int maxtries; + double thishostpercdone; + double avgdone = USI->gstats->numtargets - USI->numIncompleteHosts(); + /* next for the partially finished hosts */ + for(hostI = USI->incompleteHosts.begin(); + hostI != USI->incompleteHosts.end(); hostI++) { + host = *hostI; + maxtries = host->allowedTryno(NULL, NULL) + 1; + // This is inexact (maxtries - 1) because of numprobes_sent includes + // at least one try of ports_finished. + thishostpercdone = host->ports_finished * (maxtries -1) + host->numprobes_sent; + thishostpercdone /= maxtries * USI->gstats->numprobes; + if (thishostpercdone >= .9999) thishostpercdone = .9999; + avgdone += thishostpercdone; + } + avgdone /= USI->gstats->numtargets; + + USI->SPM->printStats(avgdone, NULL); // This prints something like SYN Stealth Scan Timing: About 1.14% done; ETC: 15:01 (0:43:23 remaining); + + log_flush(LOG_STDOUT); + + } } if (o.verbose) { @@ -3391,6 +3422,7 @@ void ultra_scan(vector &Targets, struct scan_lists *ports, (USI->gstats->num_hosts_timedout == 1)? "host" : "hosts"); } delete USI; + USI = NULL; } /* FTP bounce attack scan. This function is rather lame and should be @@ -3398,6 +3430,8 @@ void ultra_scan(vector &Targets, struct scan_lists *ports, allow FTP bounce scan, I should really allow SOCKS proxy scan. */ void bounce_scan(Target *target, u16 *portarray, int numports, struct ftpinfo *ftp) { + o.scantype = BOUNCE_SCAN; + time_t starttime; int res , sd = ftp->sd, i=0; const char *t = (const char *)target->v4hostip(); @@ -3566,6 +3600,8 @@ void reverse_testing_order(struct portinfolist *pil, struct portinfo *scanarray) scan. Now ultra_scan() does all of those, except for RPC scan, which is the only pos_scan now supported. */ void pos_scan(Target *target, u16 *portarray, int numports, stype scantype) { + o.scantype = scantype; + struct scanstats ss; int senddelay = 0; int rpcportsscanned = 0; @@ -3696,6 +3732,7 @@ void pos_scan(Target *target, u16 *portarray, int numports, stype scantype) { rsi.rpc_status = RPC_STATUS_UNKNOWN; rpcportsscanned++; + // This initial message is way down here because we don't want to print it if // no RPC ports need scanning. if (o.verbose && !printedinitialmsg) { @@ -3707,6 +3744,11 @@ void pos_scan(Target *target, u16 *portarray, int numports, stype scantype) { while(pil.testinglist != NULL) /* While we have live queries or more ports to scan */ { + + if (keyWasPressed()) { + // We can print out some status here if we want + } + /* Check the possible retransmissions first */ gettimeofday(&now, NULL); diff --git a/service_scan.cc b/service_scan.cc index 8bb1dd7a0..b65908d98 100644 --- a/service_scan.cc +++ b/service_scan.cc @@ -105,6 +105,9 @@ #include "timing.h" #include "NmapOps.h" #include "nsock.h" + +#include "tty.h" + #if HAVE_OPENSSL #include #endif @@ -1809,6 +1812,14 @@ static int scanThroughTunnel(nsock_pool nsp, nsock_iod nsi, ServiceGroup *SG, /* Prints completion estimates and the like when appropriate */ static void considerPrintingStats(ServiceGroup *SG) { + /* Check for status requests */ + if (keyWasPressed()) { + SG->SPM->printStats(SG->services_finished.size() / + ((double)SG->services_remaining.size() + SG->services_in_progress.size() + + SG->services_finished.size()), nsock_gettimeofday()); + } + + /* Perhaps this should be made more complex, but I suppose it should be good enough for now. */ if (SG->SPM->mayBePrinted(nsock_gettimeofday())) { @@ -1951,6 +1962,14 @@ void servicescan_write_handler(nsock_pool nsp, nsock_event nse, void *mydata) { SG = (ServiceGroup *) nsp_getud(nsp); nsi = nse_iod(nse); + // Check if a status message was requsted + if (keyWasPressed()) { + SG->SPM->printStats(SG->services_finished.size() / + ((double)SG->services_remaining.size() + SG->services_in_progress.size() + + SG->services_finished.size()), nsock_gettimeofday()); + } + + if (svc->target->timedOut(nsock_gettimeofday())) { end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); return; diff --git a/targets.cc b/targets.cc index 88b774b53..2e2bcedde 100644 --- a/targets.cc +++ b/targets.cc @@ -108,6 +108,7 @@ #include "TargetGroup.h" #include "Target.h" #include "scan_engine.h" +#include "tty.h" using namespace std; extern NmapOps o; @@ -1203,6 +1204,8 @@ int get_ping_results(int sd, pcap_t *pd, Target *hostbatch[], int pingtype, newportstate = PORT_UNKNOWN; while(pt->block_unaccounted > 0 && !timeout) { + keyWasPressed(); // Check for status message printing + tmpto = myto; if (pd) { diff --git a/timing.cc b/timing.cc index 6b90acbd5..402f83e99 100644 --- a/timing.cc +++ b/timing.cc @@ -264,6 +264,8 @@ ScanProgressMeter::~ScanProgressMeter() { bool ScanProgressMeter::mayBePrinted(const struct timeval *now) { struct timeval tv; + return true; + if (!o.verbose) return false; @@ -299,12 +301,9 @@ bool ScanProgressMeter::printStatsIfNeccessary(double perc_done, long time_used_ms; long time_needed_ms; long time_left_ms; - long sec_left; long prev_est_time_left_ms; /* Time left as per prev. estimate */ long change_abs_ms; /* absolute value of change */ bool printit = false; - time_t timet; - struct tm *ltime; if (!now) { gettimeofday(&tvtmp, NULL); @@ -346,6 +345,33 @@ bool ScanProgressMeter::printStatsIfNeccessary(double perc_done, } if (printit) { + return printStats(perc_done, now); + } + return false; +} + + +/* Prints an estimate of when this scan will complete. */ +bool ScanProgressMeter::printStats(double perc_done, + const struct timeval *now) { + struct timeval tvtmp; + long time_used_ms; + long time_needed_ms; + long time_left_ms; + long sec_left; + time_t timet; + struct tm *ltime; + + if (!now) { + gettimeofday(&tvtmp, NULL); + now = (const struct timeval *) &tvtmp; + } + + /* OK, now lets estimate the time to finish */ + time_used_ms = TIMEVAL_MSEC_SUBTRACT(*now, begin); + time_needed_ms = (int) ((double) time_used_ms / perc_done); + time_left_ms = time_needed_ms - time_used_ms; + /* Here we go! */ last_print = *now; TIMEVAL_MSEC_ADD(last_est, *now, time_left_ms); @@ -359,7 +385,9 @@ bool ScanProgressMeter::printStatsIfNeccessary(double perc_done, (sec_left % 3600) / 60, sec_left % 60); log_flush(LOG_STDOUT); return true; - } - return false; } + + + + diff --git a/timing.h b/timing.h index bef221bfc..58cf0abd2 100644 --- a/timing.h +++ b/timing.h @@ -151,12 +151,15 @@ class ScanProgressMeter { or not a line was printed.*/ bool printStatsIfNeccessary(double perc_done, const struct timeval *now); + /* Prints an estimate of when this scan will complete. */ + bool printStats(double perc_done, const struct timeval *now); + struct timeval begin; /* When this ScanProgressMeter was instantiated */ private: struct timeval last_print_test; /* Last time printStatsIfNeccessary was called */ struct timeval last_print; /* The most recent time the ETC was printed */ - struct timeval last_est; /* The latest PRINTED estimate */ char *scantypestr; + struct timeval last_est; /* The latest PRINTED estimate */ }; #endif /* NMAP_TIMING_H */