diff --git a/CHANGELOG b/CHANGELOG index bce03039e..9d251805f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,12 @@ # Nmap Changelog ($Id$); -*-text-*- +o Fixed an integer overflow that could occur when a target with a low + TCP timestamp clock frequency uses large timestamp values, such that + a naive uptime calculation shows a boot time before the epoch. Also + fixed a printf format specifier mismatch that was revealed by the + overflow. Toby Simmons reported the problem and helped with the fix. + [David] + o Added dhcp-discover.nse, which sends out DHCP probes on UDP/67 and displays all interesting results (or, with verbosity, all results). Optionally, multiple probes can be sent and the MAC address can be diff --git a/global_structures.h b/global_structures.h index 465d83ae3..e0d831c0a 100644 --- a/global_structures.h +++ b/global_structures.h @@ -199,7 +199,7 @@ struct seq_info { u32 timestamps[NUM_SEQ_SAMPLES]; int index; u16 ipids[NUM_SEQ_SAMPLES]; - time_t lastboot; /* 0 means unknown */ + long lastboot; /* 0 means unknown */ }; /* Different kinds of Ipids. */ diff --git a/osscan2.cc b/osscan2.cc index d17f3eafc..f4b3d5808 100644 --- a/osscan2.cc +++ b/osscan2.cc @@ -1886,6 +1886,7 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { 5) Same with ~100/sec */ if (hss->si.ts_seqclass == TS_SEQ_UNKNOWN && hss->si.responses >= 2) { + double lastboot = 0.0; avg_ts_hz = 0.0; for(i=0; i < hss->si.responses - 1; i++) { double dhz; @@ -1897,30 +1898,32 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { if (avg_ts_hz > 0 && avg_ts_hz < 5.66) { /* relatively wide range because sampling time so short and frequency so slow */ hss->si.ts_seqclass = TS_SEQ_2HZ; + lastboot = (double) hss->seq_send_times[0].tv_sec - (hss->si.timestamps[0] / 2); hss->si.lastboot = hss->seq_send_times[0].tv_sec - (hss->si.timestamps[0] / 2); } else if (avg_ts_hz > 70 && avg_ts_hz < 150) { hss->si.ts_seqclass = TS_SEQ_100HZ; - hss->si.lastboot = hss->seq_send_times[0].tv_sec - (hss->si.timestamps[0] / 100); + lastboot = (double) hss->seq_send_times[0].tv_sec - (hss->si.timestamps[0] / 100); } else if (avg_ts_hz > 724 && avg_ts_hz < 1448) { hss->si.ts_seqclass = TS_SEQ_1000HZ; - hss->si.lastboot = hss->seq_send_times[0].tv_sec - (hss->si.timestamps[0] / 1000); + lastboot = (double) hss->seq_send_times[0].tv_sec - (hss->si.timestamps[0] / 1000); } else if (avg_ts_hz > 0) { hss->si.ts_seqclass = TS_SEQ_OTHER_NUM; - hss->si.lastboot = hss->seq_send_times[0].tv_sec - (hss->si.timestamps[0] / (unsigned int)(0.5 + avg_ts_hz)); + lastboot = (double) hss->seq_send_times[0].tv_sec - (hss->si.timestamps[0] / (unsigned int)(0.5 + avg_ts_hz)); } - if (hss->si.lastboot && (hss->seq_send_times[0].tv_sec - hss->si.lastboot > 63072000)) { + if (lastboot != 0.0 && (hss->seq_send_times[0].tv_sec - lastboot > 63072000)) { /* Up 2 years? Perhaps, but they're probably lying. */ if (o.debugging) { log_write(LOG_STDOUT, "Ignoring claimed %s uptime of %lu days", hss->target->targetipstr(), (hss->seq_send_times[0].tv_sec - hss->si.lastboot) / 86400); } - hss->si.lastboot = 0; + lastboot = 0; } + hss->si.lastboot = (long) lastboot; } switch(hss->si.ts_seqclass) { diff --git a/output.cc b/output.cc index 73c4323ce..942d9f522 100644 --- a/output.cc +++ b/output.cc @@ -1706,9 +1706,11 @@ void printosscanoutput(Target *currenths) { if (currenths->seq.lastboot) { char tmbuf[128]; struct timeval tv; - gettimeofday(&tv, NULL); - strncpy(tmbuf, ctime(&(currenths->seq.lastboot)), sizeof(tmbuf)); + time_t lastboot; + lastboot = (time_t) currenths->seq.lastboot; + strncpy(tmbuf, ctime(&lastboot), sizeof(tmbuf)); chomp(tmbuf); + gettimeofday(&tv, NULL); if (o.verbose) log_write(LOG_PLAIN,"Uptime guess: %.3f days (since %s)\n", (double) (tv.tv_sec - currenths->seq.lastboot) / 86400, tmbuf); log_write(LOG_XML, "\n", tv.tv_sec - currenths->seq.lastboot, tmbuf);