📄 osscan.cc
字号:
timeout = 0; gettimeofday(&t1,NULL); /* Next we send our initial NUM_SEQ_SAMPLES SYN packets */ if (openport != (unsigned long) -1) { seq_packets_sent = 0; while (seq_packets_sent < NUM_SEQ_SAMPLES) { if (o.scan_delay) enforce_scan_delay(NULL); if (seq_packets_sent > 0) { gettimeofday(&t1, NULL); int remaining_us = 110000 - TIMEVAL_SUBTRACT(t1, seq_send_times[seq_packets_sent - 1]); if (remaining_us > 0) { /* Need to spend at least .5 seconds in sending all packets to reliably detect 2HZ timestamp sequencing */ usleep(remaining_us); } } send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false, NULL, 0, o.magic_port + seq_packets_sent + 1, openport, sequence_base + seq_packets_sent + 1, 0, 0, TH_SYN, 0, 0, (u8 *) "\003\003\012\001\002\004\001\011\010\012\077\077\077\077\000\000\000\000\000\000" , 20, NULL, 0); gettimeofday(&seq_send_times[seq_packets_sent], NULL); t1 = seq_send_times[seq_packets_sent]; seq_packets_sent++; /* Now we collect the replies */ while(si->responses < seq_packets_sent && !timeout) { if (seq_packets_sent == NUM_SEQ_SAMPLES) ip = (struct ip*) readip_pcap(pd, &bytes, oshardtimeout, NULL, &linkhdr); else ip = (struct ip*) readip_pcap(pd, &bytes, 10, NULL, &linkhdr); gettimeofday(&t2, NULL); /* error("DEBUG: got a response (len=%d):\n", bytes); */ /* lamont_hdump((unsigned char *) ip, bytes); */ /* Insure we haven't overrun our allotted time ... */ if (target->timedOut(&t2)) goto osscan_timedout; if (!ip) { if (seq_packets_sent < NUM_SEQ_SAMPLES) break; if (TIMEVAL_SUBTRACT(t2,t1) > ossofttimeout) timeout = 1; continue; } else if (TIMEVAL_SUBTRACT(t2,t1) > oshardtimeout) { timeout = 1; } if (lastipid != 0 && ip->ip_id == lastipid) { /* Probably a duplicate -- this happens sometimes when scanning localhost */ continue; } lastipid = ip->ip_id; if (bytes < (4 * ip->ip_hl) + 4U || bytes < 20) continue; setTargetMACIfAvailable(target, &linkhdr, ip, 0); if (ip->ip_p == IPPROTO_TCP) { /* readtcppacket((char *) ip, ntohs(ip->ip_len)); */ tcp = ((struct tcphdr *) (((char *) ip) + 4 * ip->ip_hl)); if (ntohs(tcp->th_dport) < o.magic_port || ntohs(tcp->th_dport) - o.magic_port > NUM_SEQ_SAMPLES || ntohs(tcp->th_sport) != openport) { continue; } if ((tcp->th_flags & TH_RST)) { /* readtcppacket((char *) ip, ntohs(ip->ip_len));*/ if (si->responses == 0) { fprintf(stderr, "WARNING: RST from port %lu -- is this port really open?\n", openport); /* We used to quit in this case, but left-overs from a SYN scan or lame-ass TCP wrappers can cause this! */ } continue; } else if ((tcp->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) { /* error("DEBUG: response is SYN|ACK to port %hu\n", ntohs(tcp->th_dport)); */ /*readtcppacket((char *)ip, ntohs(ip->ip_len));*/ /* We use the ACK value to match up our sent with rcv'd packets */ seq_response_num = (ntohl(tcp->th_ack) - 2 - sequence_base); if (seq_response_num < 0 || seq_response_num >= seq_packets_sent) { /* BzzT! Value out of range */ if (o.debugging) { error("Unable to associate os scan response with sent packet (received ack: %lX; sequence base: %lX. Packet:", (unsigned long) ntohl(tcp->th_ack), (unsigned long) sequence_base); readtcppacket((unsigned char *)ip,ntohs(ip->ip_len)); } seq_response_num = si->responses; } if (si->seqs[seq_response_num] == 0) { /* New response found! */ si->responses++; // si->seqs[seq_response_num] = ntohl(tcp->th_seq); /* TCP ISN */ si->seqs[seq_response_num] = fake_seqs[seq_response_num]; /* TCP ISN */ si->ipids[seq_response_num] = ntohs(ip->ip_id); if ((gettcpopt_ts(tcp, ×tamp, NULL) == 0)) si->ts_seqclass = TS_SEQ_UNSUPPORTED; else { if (timestamp == 0) { si->ts_seqclass = TS_SEQ_ZERO; } } si->timestamps[seq_response_num] = timestamp; /* printf("Response #%d -- ipid=%hu ts=%i\n", seq_response_num, ntohs(ip->ip_id), timestamp); */ if (si->responses > 1) { seq_diffs[si->responses-2] = MOD_DIFF(ntohl(tcp->th_seq), si->seqs[si->responses-2]); } } } } } } /* Now we make sure there are no gaps in our response array ... */ for(i=0, si->responses=0; i < seq_packets_sent; i++) { if (si->seqs[i] != 0) /* We found a good one */ { if (si->responses < i) { si->seqs[si->responses] = si->seqs[i]; si->ipids[si->responses] = si->ipids[i]; si->timestamps[si->responses] = si->timestamps[i]; seq_send_times[si->responses] = seq_send_times[i]; } if (si->responses > 0) { seq_diffs[si->responses - 1] = MOD_DIFF(si->seqs[si->responses], si->seqs[si->responses - 1]); ts_diffs[si->responses - 1] = MOD_DIFF(si->timestamps[si->responses], si->timestamps[si->responses - 1]); time_usec_diffs[si->responses - 1] = TIMEVAL_SUBTRACT(seq_send_times[si->responses], seq_send_times[si->responses - 1]); if (!time_usec_diffs[si->responses - 1]) time_usec_diffs[si->responses - 1]++; /* We divide by this later */ /* printf("MOD_DIFF_USHORT(%hu, %hu) == %hu\n", si->ipids[si->responses], si->ipids[si->responses - 1], MOD_DIFF_USHORT(si->ipids[si->responses], si->ipids[si->responses - 1])); */ } si->responses++; } /* Otherwise nothing good in this slot to copy */ } si->ipid_seqclass = ipid_sequence(si->responses, si->ipids, islocalhost(target->v4hostip())); /* 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 (si->ts_seqclass == TS_SEQ_UNKNOWN && si->responses >= 2) { avg_ts_hz = 0.0; for(i=0; i < 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 / ( si->responses - 1); } if (o.debugging) printf("The avg TCP TS HZ is: %f\n", 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 */ si->ts_seqclass = TS_SEQ_2HZ; si->lastboot = seq_send_times[0].tv_sec - (si->timestamps[0] / 2); } else if (avg_ts_hz > 85 && avg_ts_hz < 115) { si->ts_seqclass = TS_SEQ_100HZ; si->lastboot = seq_send_times[0].tv_sec - (si->timestamps[0] / 100); } else if (avg_ts_hz > 900 && avg_ts_hz < 1100) { si->ts_seqclass = TS_SEQ_1000HZ; si->lastboot = seq_send_times[0].tv_sec - (si->timestamps[0] / 1000); } if (si->lastboot && (seq_send_times[0].tv_sec - si->lastboot > 63072000)) { /* Up 2 years? Perhaps, but they're probably lying. */ if (o.debugging) { error("Ignoring claimed uptime of %lu days", (seq_send_times[0].tv_sec - si->lastboot) / 86400); } si->lastboot = 0; } } /* Time to look at the TCP ISN predictability */ if (si->responses >= 4 && o.scan_delay <= 1000) { seq_gcd = gcd_n_uint(si->responses -1, seq_diffs); /* printf("The GCD is %u\n", seq_gcd);*/ if (seq_gcd) { for(i=0; i < si->responses - 1; i++) seq_diffs[i] /= seq_gcd; for(i=0; i < si->responses - 1; i++) { if (MOD_DIFF(si->seqs[i+1],si->seqs[i]) > 50000000) { si->seqclass = SEQ_TR; si->index = 9999999; /* printf("Target is a TR box\n");*/ break; } seq_avg_inc += seq_diffs[i]; } } if (seq_gcd == 0) { si->seqclass = SEQ_CONSTANT; si->index = 0; } else if (seq_gcd % 64000 == 0) { si->seqclass = SEQ_64K; /* printf("Target is a 64K box\n");*/ si->index = 1; } else if (seq_gcd % 800 == 0) { si->seqclass = SEQ_i800; /* printf("Target is a i800 box\n");*/ si->index = 10; } else if (si->seqclass == SEQ_UNKNOWN) { seq_avg_inc = (unsigned int) ((0.5) + seq_avg_inc / (si->responses - 1)); /* printf("seq_avg_inc=%u\n", seq_avg_inc);*/ for(i=0; i < si->responses -1; i++) { /* printf("The difference is %u\n", seq_diffs[i]); printf("Adding %u^2=%e", MOD_DIFF(seq_diffs[i], seq_avg_inc), pow(MOD_DIFF(seq_diffs[i], seq_avg_inc), 2));*/ /* pow() seems F#@!#$!ed up on some Linux systems so I will not use it for now seq_inc_sum += pow(MOD_DIFF(seq_diffs[i], seq_avg_inc), 2); */ seq_inc_sum += ((double)(MOD_DIFF(seq_diffs[i], seq_avg_inc)) * ((double)MOD_DIFF(seq_diffs[i], seq_avg_inc))); /* seq_inc_sum += pow(MOD_DIFF(seq_diffs[i], seq_avg_inc), 2);*/ } /* printf("The sequence sum is %e\n", seq_inc_sum);*/ seq_inc_sum /= (si->responses - 1); si->index = (unsigned int) (0.5 + sqrt(seq_inc_sum)); /* printf("The sequence index is %d\n", si->index);*/ if (si->index < 75) { si->seqclass = SEQ_TD; /* printf("Target is a Micro$oft style time dependant box\n");*/ } else { si->seqclass = SEQ_RI; /* printf("Target is a random incremental box\n");*/ } } FPtests[0] = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); FPtests[0]->name = "TSeq"; seq_AVs = (struct AVal *) safe_zalloc(sizeof(struct AVal) * 5); FPtests[0]->results = seq_AVs; avnum = 0; seq_AVs[avnum].attribute = "Class"; switch(si->seqclass) { case SEQ_CONSTANT: strcpy(seq_AVs[avnum].value, "C"); seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute= "Val"; sprintf(seq_AVs[avnum].value, "%X", si->seqs[0]); break; case SEQ_64K: strcpy(seq_AVs[avnum].value, "64K"); break; case SEQ_i800: strcpy(seq_AVs[avnum].value, "i800"); break; case SEQ_TD: strcpy(seq_AVs[avnum].value, "TD"); 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="SI"; sprintf(seq_AVs[avnum].value, "%X", si->index); break; case SEQ_RI: strcpy(seq_AVs[avnum].value, "RI"); 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="SI"; sprintf(seq_AVs[avnum].value, "%X", si->index); break; case SEQ_TR: strcpy(seq_AVs[avnum].value, "TR"); break; } /* IP ID Class */ switch(si->ipid_seqclass) { case IPID_SEQ_CONSTANT: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "IPID"; strcpy(seq_AVs[avnum].value, "C"); break; case IPID_SEQ_INCR: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "IPID"; 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 = "IPID"; strcpy(seq_AVs[avnum].value, "BI"); break; case IPID_SEQ_RPI: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "IPID"; strcpy(seq_AVs[avnum].value, "RPI"); break; case IPID_SEQ_RD: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "IPID"; strcpy(seq_AVs[avnum].value, "RD"); break; case IPID_SEQ_ZERO: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "IPID"; strcpy(seq_AVs[avnum].value, "Z"); break; } /* TCP Timestamp option sequencing */ switch(si->ts_seqclass) { case TS_SEQ_ZERO: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TS"; strcpy(seq_AVs[avnum].value, "0"); break; case TS_SEQ_2HZ: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TS"; strcpy(seq_AVs[avnum].value, "2HZ"); break; case TS_SEQ_100HZ: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TS"; strcpy(seq_AVs[avnum].value, "100HZ"); break; case TS_SEQ_1000HZ: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TS"; strcpy(seq_AVs[avnum].value, "1000HZ"); break; case TS_SEQ_UNSUPPORTED: seq_AVs[avnum].next = &seq_AVs[avnum+1]; avnum++; seq_AVs[avnum].attribute = "TS"; strcpy(seq_AVs[avnum].value, "U"); break; } } else { log_write(LOG_STDOUT|LOG_NORMAL|LOG_SKID,"Insufficient responses for TCP sequencing (%d), OS detection may be less accurate\n", si->responses); } } else { } for(i=0; i < 9; i++) { if (i > 0 && !FPtests[i] && ((openport != (unsigned long) -1) || i > 4)) { /* 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 */ FPtests[i] = (FingerPrint *) safe_zalloc(sizeof(FingerPrint)); seq_AVs = (struct AVal *) safe_zalloc(sizeof(struct AVal)); seq_AVs->attribute = "Resp"; strcpy(seq_AVs->value, "N"); seq_AVs->next = NULL; FPtests[i]->results = seq_AVs; FPtests[i]->name = (i == 1)? "T1" : (i == 2)? "T2" : (i == 3)? "T3" : (i == 4)? "T4" : (i == 5)? "T5" : (i == 6)? "T6" : (i == 7)? "T7" : "PU"; } } last = -1; FP = NULL; for(i=0; i < 9 ; i++) { if (!FPtests[i]) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -