From 3768236c47a89dc261b62fb8c4c70be1e9120c50 Mon Sep 17 00:00:00 2001 From: fyodor Date: Wed, 30 Aug 2006 07:38:30 +0000 Subject: [PATCH] More OS detection changes. We're really getting close now --- nmap-os-db | 22 +++++++++-------- nmap-service-probes | 2 +- nmap.cc | 2 +- osscan2.cc | 59 +++++++++++++++++++++++++-------------------- utils.h | 5 +++- 5 files changed, 51 insertions(+), 39 deletions(-) diff --git a/nmap-os-db b/nmap-os-db index 1da38810c..abfead478 100644 --- a/nmap-os-db +++ b/nmap-os-db @@ -26,37 +26,39 @@ # Linux 2.6.12-1.1380_FC3 #1 Wed Oct 19 20:34:13 EDT 2005 i686 i686 i386 GNU/Linux Fingerprint Linux 2.6.12-1.1380_FC3 (Fedora Core 3) Class Linux | Linux | 2.6.X | general purpose -SEQ(SP=AA-B4%GCD=<5%ISR=C0-D0%TI=Z%II=I%TS=A) +SEQ(SP=9E-B0%GCD=<5%ISR=C0-CE%TI=Z%II=I%TS=A) OPS(O1=M5B4ST11NW2%O2=M5B4ST11NW2%O3=M5B4NNT11NW2%O4=M5B4ST11NW2%O5=M5B4ST11NW2%O6=M5B4ST11) WIN(W1=16A0%W2=16A0%W3=16A0%W4=16A0%W5=16A0%W6=16A0) ECN(R=Y%DF=Y%T=40%TG=40%W=16D0%O=M5B4NNSNW2%CC=N%Q=) -T1(R=Y%DF=Y%T=40%TG=40%S=O%A=S+|S+|S+%F=AS%RD=0%Q=) +T1(R=Y%DF=Y%T=40%TG=40%S=O%A=S+%F=AS%RD=0%Q=) T2(R=N) -T3(R=Y%DF=Y%T=40%TG=40%W=16A0%S=O%A=S+|S+|S+%F=AS%O=M5B4ST11NW2%RD=0%Q=) +T3(R=Y%DF=Y%T=40%TG=40%W=16A0%S=O%A=S+%F=AS%O=M5B4ST11NW2%RD=0%Q=) T4(R=Y%DF=Y%T=40%TG=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=) -T5(R=Y%DF=Y%T=40%TG=40%W=0%S=Z%A=S+|S+|S+%F=AR%O=%RD=0%Q=) +T5(R=Y%DF=Y%T=40%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=) T6(R=Y%DF=Y%T=40%TG=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=) -T7(R=Y%DF=Y%T=40%TG=40%W=0%S=Z%A=S+|S+|S+%F=AR%O=%RD=0%Q=) +T7(R=Y%DF=Y%T=40%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=) U1(DF=N%T=40%TG=40%TOS=C0%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUL=G%RUD=G) IE(DFI=N%T=40%TG=40%TOSI=S%CD=S%SI=S%DLI=S) + # Linux 2.6.17-1.2157_FC5 #1 SMP Tue Jul 11 22:53:56 EDT 2006 x86_64 x86_64 x86_64 GNU/Linux Fingerprint Linux 2.6.17-1.2157_FC5 (Fedora Core 5) Class Linux | Linux | 2.6.X | general purpose -SEQ(SP=A3-B5%GCD=<3%ISR=C8-D0%TI=Z%II=I%TS=8) +SEQ(SP=A0-B6%GCD=<5%ISR=C0-D3%TI=Z%II=I%TS=8) OPS(O1=M400CST11NW7%O2=M400CST11NW7%O3=M400CNNT11NW7%O4=M400CST11NW7%O5=M400CST11NW7%O6=M400CST11) WIN(W1=8000%W2=8000%W3=8000%W4=8000%W5=8000%W6=8000) ECN(R=Y%DF=Y%T=40%TG=40%W=8018%O=M400CNNSNW7%CC=N%Q=) -T1(R=Y%DF=Y%T=40%TG=40%S=O%A=S+|S+%F=AS%RD=0%Q=) +T1(R=Y%DF=Y%T=40%TG=40%S=O%A=S+%F=AS%RD=0%Q=) T2(R=N) -T3(R=Y%DF=Y%T=40%TG=40%W=8000%S=O%A=S+|S+%F=AS%O=M400CST11NW7%RD=0%Q=) +T3(R=Y%DF=Y%T=40%TG=40%W=8000%S=O%A=S+%F=AS%O=M400CST11NW7%RD=0%Q=) T4(R=Y%DF=Y%T=40%TG=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=) -T5(R=Y%DF=Y%T=40%TG=40%W=0%S=Z%A=S+|S+%F=AR%O=%RD=0%Q=) +T5(R=Y%DF=Y%T=40%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=) T6(R=Y%DF=Y%T=40%TG=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=) -T7(R=Y%DF=Y%T=40%TG=40%W=0%S=Z%A=S+|S+%F=AR%O=%RD=0%Q=) +T7(R=Y%DF=Y%T=40%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=) U1(DF=N%T=40%TG=40%TOS=C0%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUL=G%RUD=G) IE(DFI=N%T=40%TG=40%TOSI=S%CD=S%SI=S%DLI=S) + # Linux 2.6.16-1.2096_FC5 #1 SMP Wed Apr 19 05:14:26 EDT 2006 x86_64 x86_64 x86_64 GNU/Linux Fingerprint Linux 2.6.16-1.2095_FC5 (Fedora Core 5) Class Linux | Linux | 2.6.X | general purpose diff --git a/nmap-service-probes b/nmap-service-probes index 0d9d5606a..a063bd89f 100644 --- a/nmap-service-probes +++ b/nmap-service-probes @@ -1275,7 +1275,7 @@ match service-monitor m|^\0\0\0\x18\0\0..\0\0..\xff\xff\xff\xff\xff\xff\xff\xff\ match smtp-proxy m|^220 ([\w-_.]+) PGP Universal service ready \(proxied server greeted us with: (.*)\)\r\n| p/PGP Universal smtp proxy/ h/$1/ i/Proxied greeting: $2/ match smtp m|^220 ([-/.+\w]+) MailGate ready for ESMTP on | p/MailGate smtpd/ h/$1/ o/Windows/ -match smtp m|^220 ([-/.+\w]+) ESMTP bitdefender| p/BitDefender anti-virus mail gateway/ h/$1/ o/Unix/ i/based on Postfix/ +match smtp m|^220 ([-/.+\w]+) ESMTP bitdefender| p/BitDefender anti-virus mail gateway/ h/$1/ match smtp m|^220 ([-/.+\w]+) SMTP ready to roll\r\n| p/Hotmail Popper hotmail to smtp gateway/ h/$1/ match smtp m|^220 ([-/.+\w]+) AvMailGate-(\d[-.\w]+)\r\n| p/AvMailGate smtp anti-virus mail gateway/ h/$1/ v/$2/ match smtp m|^220 ([-/.+\w]+) Internet Rex ESMTP daemon at your service\.\r\n| p/Internet Rex smtpd/ h/$1/ diff --git a/nmap.cc b/nmap.cc index c9b44094e..0216e7122 100644 --- a/nmap.cc +++ b/nmap.cc @@ -234,7 +234,7 @@ printf("%s %s ( %s )\n" " --version-all: Try every single probe (intensity 9)\n" " --version-trace: Show detailed version scan activity (for debugging)\n" "OS DETECTION:\n" - " -O: Enable OS detection (try 2nd generation, then 1st if that fails)\n" + " -O: Enable OS detection (try 2nd generation w/fallback to 1st)\n" " -O2: Only use the new OS detection system (no fallback)\n" " -O1: Only use the old (1st generation) OS detection system\n" " --osscan-limit: Limit OS detection to promising targets\n" diff --git a/osscan2.cc b/osscan2.cc index 302644c00..eb5b80f8f 100644 --- a/osscan2.cc +++ b/osscan2.cc @@ -579,6 +579,9 @@ HostOsScanStats::HostOsScanStats(Target * t) { target = t; FP = NULL; + bzero(&si, sizeof(si)); + bzero(&ipid, sizeof(ipid)); + openTCPPort = -1; closedTCPPort = -1; closedUDPPort = -1; @@ -1600,11 +1603,12 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { int i,j; u32 seq_diffs[NUM_SEQ_SAMPLES]; u32 ts_diffs[NUM_SEQ_SAMPLES]; + float seq_rates[NUM_SEQ_SAMPLES]; unsigned long time_usec_diffs[NUM_SEQ_SAMPLES]; int avnum; double seq_stddev = 0; double seq_rate = 0; - unsigned int seq_avg_inc = 0; + double seq_avg_rate = 0; double avg_ts_hz = 0.0; /* Avg. amount that timestamps incr. each second */ u32 seq_gcd = 1; int tcp_ipid_seqclass; /* TCP IPID SEQ TYPE defines in nmap.h */ @@ -1624,16 +1628,22 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { } if (j > 0) { seq_diffs[j - 1] = MOD_DIFF(hss->si.seqs[j], hss->si.seqs[j - 1]); + ts_diffs[j - 1] = MOD_DIFF(hss->si.timestamps[j], hss->si.timestamps[j - 1]); time_usec_diffs[j - 1] = TIMEVAL_SUBTRACT(hss->seq_send_times[j], hss->seq_send_times[j - 1]); if (!time_usec_diffs[j - 1]) time_usec_diffs[j - 1]++; /* We divide by this later */ + /* Rate of ISN increase per second */ + seq_rates[j - 1] = seq_diffs[j-1] * 1000000.0 / time_usec_diffs[j-1]; + seq_avg_rate += seq_rates[j-1]; } j++; } /* Otherwise nothing good in this slot to copy */ } - hss->si.responses = j; /* Just an ensurance */ - + hss->si.responses = j; /* Just for assurance */ + seq_avg_rate /= hss->si.responses - 1; + seq_rate = seq_avg_rate; + /* Now we look at TCP Timestamp sequence prediction */ /* Battle plan: 1) Compute average increments per second, and variance in incr. per second @@ -1652,8 +1662,8 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { avg_ts_hz += dhz / ( hss->si.responses - 1); } - if (o.debugging) - printf("The avg TCP TS HZ of %s is: %f\n", hss->target->targetipstr(), avg_ts_hz); + /* if (o.debugging) + printf("The avg TCP TS HZ of %s is: %f\n", hss->target->targetipstr(), avg_ts_hz); */ if (avg_ts_hz > 0 && avg_ts_hz < 3.9) { /* relatively wide range because sampling time so short and frequency so slow */ hss->si.ts_seqclass = TS_SEQ_2HZ; @@ -1696,30 +1706,27 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { hss->si.index = 0; } else { - /* First calculate the average counter rate */ - for(i=0; i < hss->si.responses - 1; i++) { - seq_rate += seq_diffs[i] / (TIMEVAL_MSEC_SUBTRACT(hss->seq_send_times[i+1], hss->seq_send_times[i]) / 1000.0); - } - seq_rate /= hss->si.responses - 1; /* Finally we take a binary logarithm, multiply by 8, and round to get the final result */ seq_rate = log(seq_rate) / log(2); seq_rate = (unsigned int) (seq_rate * 8 + 0.5); - /* Now calculate the predictability index */ - for(i=0; i < hss->si.responses - 1; i++) - seq_diffs[i] /= seq_gcd; + /* Normally we don't divide by gcd in computing the rate stddev + because otherwise we'll get an artificially low value about + 1/32 of the time if the responses all happen to be even. On + the other hand, if a system inherently uses a large gcd such + as 64,000, we want to get rid of it. So as a compromise, we + divide by the gcd if it is at least 9 */ + + int div_gcd = 1; + if (seq_gcd > 9) + div_gcd = seq_gcd; + for(i=0; i < hss->si.responses - 1; i++) { - seq_avg_inc += seq_diffs[i]; - } - seq_avg_inc = (unsigned int) ((0.5) + seq_avg_inc / (hss->si.responses - 1)); - for(i=0; i < hss->si.responses -1; i++) { - /* pow() seems F#@!#$!ed up on some Linux systems so I will - not use it for now - */ - seq_stddev += ((double)(MOD_DIFF(seq_diffs[i], seq_avg_inc)) * - ((double)MOD_DIFF(seq_diffs[i], seq_avg_inc))); + double rtmp = seq_rates[i] / div_gcd - seq_avg_rate / div_gcd; + seq_stddev += rtmp * rtmp; } + /* We divide by ((numelements in seq_diffs) - 1), which is (si.responses - 2), because that gives a better approx of std. dev when you're only looking at a subset of whole @@ -1749,7 +1756,7 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { seq_AVs[avnum].attribute = "SP"; sprintf(seq_AVs[avnum].value, "%X", hss->si.index); seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; - seq_AVs[avnum].attribute= "GCD"; + seq_AVs[avnum].attribute= "GCD"; sprintf(seq_AVs[avnum].value, "%X", seq_gcd); seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute= "ISR"; @@ -1886,10 +1893,10 @@ void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { case TS_SEQ_2HZ: case TS_SEQ_100HZ: case TS_SEQ_1000HZ: - case TS_SEQ_OTHER_NUM: + case TS_SEQ_OTHER_NUM: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TS"; - sprintf(seq_AVs[avnum].value, "%X", (unsigned int)(0.5 + log(avg_ts_hz)/log(2.0))); + sprintf(seq_AVs[avnum].value, "%X", (unsigned int)(0.5 + log(avg_ts_hz)/log(2.0))); break; case TS_SEQ_UNSUPPORTED: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; @@ -3115,7 +3122,7 @@ int get_ipid_sequence(int numSamples, int *ipids, int islocalhost) { if (ipids[i-1] <= ipids[i]) { ipid_diffs[i-1] = ipids[i] - ipids[i-1]; } else { - ipid_diffs[i-1] = u16(ipids[i] - ipids[i-1] + 65536); + ipid_diffs[i-1] = (u16) (ipids[i] - ipids[i-1] + 65536); } /* Random */ diff --git a/utils.h b/utils.h index e29f01369..3c4e63c3f 100644 --- a/utils.h +++ b/utils.h @@ -141,9 +141,12 @@ #include "nmap.h" #include "global_structures.h" +/* Arithmatic difference modulo 2^32 */ #ifndef MOD_DIFF -#define MOD_DIFF(a,b) ((unsigned long) (MIN((unsigned long)(a) - (unsigned long ) (b), (unsigned long )(b) - (unsigned long) (a)))) +#define MOD_DIFF(a,b) ((u32) (MIN((u32)(a) - (u32 ) (b), (u32 )(b) - (u32) (a)))) #endif + +/* Arithmatic difference modulo 2^16 */ #ifndef MOD_DIFF_USHORT #define MOD_DIFF_USHORT(a,b) ((MIN((unsigned short)((unsigned short)(a) - (unsigned short ) (b)), (unsigned short) ((unsigned short )(b) - (unsigned short) (a))))) #endif