📄 osscan2.cc
字号:
this->stats->num_probes_active--; return true; } return false;}void HostOsScan::makeFP(HostOsScanStats *hss) { assert(hss); int i; int last; FingerPrint *FP; struct AVal *pAV; int ttl; if(!hss->FP_TSeq) makeTSeqFP(hss); if(!hss->FP_TOps) makeTOpsFP(hss); if(!hss->FP_TWin) makeTWinFP(hss); for(i=3; i < NUM_FPTESTS; i++) { if (!hss->FPtests[i] && ((i>=3 && i<=7 && hss->openTCPPort != -1) || (i>=8 && i<=10 && hss->target->FPR->osscan_closedtcpport != -1) || i>=11)) { /* We create a Resp (response) attribute with value of N (no) because it is important here to note whether responses were or were not received */ hss->FPtests[i] = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); pAV = (struct AVal *) safe_zalloc(sizeof(struct AVal)); pAV->attribute = "R"; strcpy(pAV->value, "N"); pAV->next = NULL; hss->FPtests[i]->results = pAV; hss->FPtests[i]->name = (i == 3)? "ECN" : (i == 4)? "T1" : (i == 5)? "T2" : (i == 6)? "T3" : (i == 7)? "T4" : (i == 8)? "T5" : (i == 9)? "T6" : (i == 10)? "T7" : (i == 11)? "U1" : "IE"; } else if(hss->FPtests[i]) { /* Replace TTL with initial TTL. */ for(pAV = hss->FPtests[i]->results; pAV; pAV = pAV->next) { if(pAV->attribute == "T") { /* Found TTL item. The value for this attribute is the received TTL encoded in decimal. We replace it with the initial TTL encoded in hex. */ ttl = atoi(pAV->value); if(hss->distance_guess == -1) hss->distance_guess = get_initial_ttl_guess(ttl) - ttl; if(hss->distance != -1) { /* We've gotten response for the UDP probe and thus have the "true" hop count. Add the received TTL to the hop count to get the initial TTL. */ sprintf(pAV->value, "%hX", ttl + hss->distance); } else { /* Guess the initial TTL value */ pAV->attribute = "TG"; sprintf(pAV->value, "%hX", get_initial_ttl_guess(ttl)); } break; } } } } /* Link them up. */ last = -1; FP = NULL; for(i=0; i < NUM_FPTESTS ; i++) { if (!hss->FPtests[i]) continue; if (!FP) FP = hss->FPtests[i]; if (last > -1) { hss->FPtests[last]->next = hss->FPtests[i]; } last = i; } if (last != -1) hss->FPtests[last]->next = NULL; /* printf("%s", fp2ascii(FP)); */ hss->FP = FP;}void HostOsScan::makeTSeqFP(HostOsScanStats *hss) { if (!hss->si.responses) return; 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; 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 */ int icmp_ipid_seqclass; /* ICMP IPID SEQ TYPE defines in nmap.h */ int good_tcp_ipid_num, good_icmp_ipid_num; int tsnewval = 0; struct AVal *seq_AVs; /* Now we make sure there are no gaps in our response array ... */ for(i=0, j=0; i < NUM_SEQ_SAMPLES; i++) { if (hss->si.seqs[i] != 0) /* We found a good one */ { if (j < i) { hss->si.seqs[j] = hss->si.seqs[i]; hss->si.ipids[j] = hss->si.ipids[i]; hss->si.timestamps[j] = hss->si.timestamps[i]; hss->seq_send_times[j] = hss->seq_send_times[i]; } 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 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 2) If any are 0, set to constant 3) If variance is high, set to random incr. [ skip for now ] 4) if ~10/second, set to appropriate thing 5) Same with ~100/sec */ if (hss->si.ts_seqclass == TS_SEQ_UNKNOWN && hss->si.responses >= 2) { avg_ts_hz = 0.0; for(i=0; i < hss->si.responses - 1; i++) { double dhz; dhz = (double) ts_diffs[i] / (time_usec_diffs[i] / 1000000.0); /* printf("ts incremented by %d in %li usec -- %fHZ\n", ts_diffs[i], time_usec_diffs[i], dhz); */ avg_ts_hz += dhz / ( hss->si.responses - 1); } 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; 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); } 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); } 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)); } if (hss->si.lastboot && (hss->seq_send_times[0].tv_sec - hss->si.lastboot > 63072000)) { /* Up 2 years? Perhaps, but they're probably lying. */ if (o.debugging) { error("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; } } /* Time to look at the TCP ISN predictability */ if (hss->si.responses >= 4 && o.scan_delay <= 1000) { /* First calculate the GCD */ seq_gcd = gcd_n_uint(hss->si.responses -1, seq_diffs); if (!seq_gcd) { /* Constant ISN */ seq_rate = 0; seq_stddev = 0; hss->si.index = 0; } else { /* Finally we take a binary logarithm, multiply by 8, and round to get the final result */ seq_rate = log(seq_rate) / log(2.0); seq_rate = (unsigned int) (seq_rate * 8 + 0.5); /* 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++) { 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 population. */ seq_stddev /= hss->si.responses - 2; /* Next we need to take the square root of this value */ seq_stddev = sqrt(seq_stddev); /* Finally we take a binary logarithm, multiply by 8, and round to get the final result */ if (seq_stddev <= 1) hss->si.index = 0; else { seq_stddev = log(seq_stddev) / log(2.0); hss->si.index = (int) (seq_stddev * 8 + 0.5); } } /* Time to generate the SEQ probe line of the fingerprint */ hss->FP_TSeq = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); hss->FP_TSeq->name = "SEQ"; seq_AVs = (struct AVal *) safe_zalloc(sizeof(struct AVal) * 7); hss->FP_TSeq->results = seq_AVs; avnum = 0; 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"; sprintf(seq_AVs[avnum].value, "%X", seq_gcd); seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute= "ISR"; sprintf(seq_AVs[avnum].value, "%X", (unsigned int) seq_rate); /* Now it is time to deal with IPIDs */ good_tcp_ipid_num = 0; good_icmp_ipid_num = 0; for(i=0; i < NUM_SEQ_SAMPLES; i++) { if (hss->ipid.tcp_ipids[i] != -1) { if (good_tcp_ipid_num < i) { hss->ipid.tcp_ipids[good_tcp_ipid_num] = hss->ipid.tcp_ipids[i]; } good_tcp_ipid_num++; } if (hss->ipid.icmp_ipids[i] != -1) { if (good_icmp_ipid_num < i) { hss->ipid.icmp_ipids[good_icmp_ipid_num] = hss->ipid.icmp_ipids[i]; } good_icmp_ipid_num++; } } if (good_tcp_ipid_num >= 3) { tcp_ipid_seqclass = get_ipid_sequence(good_tcp_ipid_num, hss->ipid.tcp_ipids, islocalhost(hss->target->v4hostip())); } else { tcp_ipid_seqclass = IPID_SEQ_UNKNOWN; } /* Only print tcp ipid seqclass in the final report. */ hss->si.ipid_seqclass = tcp_ipid_seqclass; if (good_icmp_ipid_num >= 2) { icmp_ipid_seqclass = get_ipid_sequence(good_icmp_ipid_num, hss->ipid.icmp_ipids, islocalhost(hss->target->v4hostip())); } else { icmp_ipid_seqclass = IPID_SEQ_UNKNOWN; } /* TI: TCP IP ID sequence generation algorithm */ switch(tcp_ipid_seqclass) { case IPID_SEQ_CONSTANT: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TI"; sprintf(seq_AVs[avnum].value, "%X", hss->ipid.tcp_ipids[0]); break; case IPID_SEQ_INCR: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TI"; strcpy(seq_AVs[avnum].value, "I"); break; case IPID_SEQ_BROKEN_INCR: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TI"; strcpy(seq_AVs[avnum].value, "BI"); break; case IPID_SEQ_RPI: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TI"; strcpy(seq_AVs[avnum].value, "RI"); break; case IPID_SEQ_RD: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TI"; strcpy(seq_AVs[avnum].value, "RD"); break; case IPID_SEQ_ZERO: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TI"; strcpy(seq_AVs[avnum].value, "Z"); break; } /* II: ICMP IP ID sequence generation algorithm */ switch(icmp_ipid_seqclass) { case IPID_SEQ_CONSTANT: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "II"; sprintf(seq_AVs[avnum].value, "%X", hss->ipid.icmp_ipids[0]); break; case IPID_SEQ_INCR: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "II"; strcpy(seq_AVs[avnum].value, "I"); break; case IPID_SEQ_BROKEN_INCR: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "II"; strcpy(seq_AVs[avnum].value, "BI"); break; case IPID_SEQ_RPI: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "II"; strcpy(seq_AVs[avnum].value, "RI"); break; case IPID_SEQ_RD: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "II"; strcpy(seq_AVs[avnum].value, "RD"); break; case IPID_SEQ_ZERO: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "II"; strcpy(seq_AVs[avnum].value, "Z"); break; } /* SS: Shared IP ID sequence boolean */ if ( (tcp_ipid_seqclass == IPID_SEQ_INCR || tcp_ipid_seqclass == IPID_SEQ_BROKEN_INCR || tcp_ipid_seqclass == IPID_SEQ_RPI) && (icmp_ipid_seqclass == IPID_SEQ_INCR || icmp_ipid_seqclass == IPID_SEQ_BROKEN_INCR || icmp_ipid_seqclass == IPID_SEQ_RPI)) { /* Both are incremental. Thus we have "SS" test. Check if they are in the same sequence. */ seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "SS"; int avg = (hss->ipid.tcp_ipids[good_tcp_ipid_num-1] - hss->ipid.tcp_ipids[0]) / (good_tcp_ipid_num - 1); if ( hss->ipid.icmp_ipids[0] < hss->ipid.tcp_ipids[good_tcp_ipid_num-1] + 3 * avg) { strcpy(seq_AVs[avnum].value, "S"); } else { strcpy(seq_AVs[avnum].value, "O"); } } /* TCP Timestamp option sequencing */ switch(hss->si.ts_seqclass) { case TS_SEQ_ZERO: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TS"; str
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -