1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-08 05:31:31 +00:00

Added Zhao changes which cause packet-trace to print tcp ops, slight changes to new os detection, and update fingerfix.pl for recent os detection changes

This commit is contained in:
fyodor
2006-08-20 18:17:03 +00:00
parent cd233fca26
commit 1da53c8366
4 changed files with 212 additions and 48 deletions

View File

@@ -2,7 +2,7 @@
4.20ALPHA5
o Worked with Zhao to improve the new OS detection system with
better algorithms and bug fixes.
better algorithms, some probe changes, and some bug fixes.
o Nmap now uses the (relatively) new libpcap pcap_get_selectable_fd
API on systems which support it. This means that we no longer need

View File

@@ -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" "08/16/2006" "" "Nmap Reference Guide"
.TH "NMAP" "1" "08/19/2006" "" "Nmap Reference Guide"
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)

View File

@@ -301,7 +301,7 @@ public:
private:
/* Ports of the targets used in os fingerprinting. */
unsigned long openTCPPort, closedTCPPort, closedUDPPort;
int openTCPPort, closedTCPPort, closedUDPPort;
/* Probe list used in tests. At first, probes are linked in
* probesToSend; when a probe is sent, it will be removed from
@@ -567,9 +567,9 @@ HostOsScanStats::HostOsScanStats(Target * t) {
target = t;
FP = NULL;
openTCPPort = (unsigned int)-1;
closedTCPPort = (unsigned int)-1;
closedUDPPort = (unsigned int)-1;
openTCPPort = -1;
closedTCPPort = -1;
closedUDPPort = -1;
num_probes_sent = 0;
sendDelayMs = MAX(o.scan_delay, OS_PROBE_DELAY);
@@ -631,7 +631,7 @@ void HostOsScanStats::initScanStats() {
int i;
/* Lets find an open port to use if we don't already have one */
openTCPPort = (unsigned long) -1;
openTCPPort = -1;
/* target->FPR->osscan_opentcpport = -1;
target->FPR->osscan_closedtcpport = -1;
target->FPR->osscan_closedudpport = -1; */
@@ -694,8 +694,8 @@ void HostOsScanStats::initScanStats() {
closedUDPPort = (get_random_uint() % 14781) + 30000;
}
if (o.verbose && openTCPPort != (unsigned long) -1)
log_write(LOG_STDOUT, "OSScan against host %s: assuming TCP port %lu is open, %lu is closed, UDP port %lu is closed and none is firewalled\n",
if (o.verbose && openTCPPort != -1)
log_write(LOG_STDOUT, "OSScan against host %s: assuming TCP port %d is open, %d is closed, UDP port %d is closed and none is firewalled\n",
target->targetipstr(), openTCPPort, closedTCPPort, closedUDPPort);
FP = NULL;
@@ -933,7 +933,7 @@ void HostOsScan::reInitScanSystem() {
void HostOsScan::buildSeqProbeList(HostOsScanStats *hss) {
assert(hss);
int i;
if(hss->openTCPPort == (unsigned long)-1) return;
if(hss->openTCPPort == -1) return;
if(hss->FP_TSeq) return;
for(i=0; i<NUM_SEQ_SAMPLES; i++)
@@ -989,7 +989,7 @@ void HostOsScan::buildTUIProbeList(HostOsScanStats *hss) {
hss->addNewProbe(OFP_TUDP, 0);
}
if(hss->openTCPPort != (unsigned long)-1) {
if(hss->openTCPPort != -1) {
/* tops/twin probes. We send the probe again if we didn't get a
response by the corresponding seq probe.
*/
@@ -1254,7 +1254,7 @@ void HostOsScan::sendTSeqProbe(HostOsScanStats *hss, int probeNo) {
assert(hss);
assert(probeNo >= 0 && probeNo < NUM_SEQ_SAMPLES);
if(hss->openTCPPort == (unsigned long)-1) return;
if(hss->openTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
tcpPortBase + probeNo, hss->openTCPPort,
@@ -1269,21 +1269,24 @@ void HostOsScan::sendTOpsProbe(HostOsScanStats *hss, int probeNo) {
assert(hss);
assert(probeNo>=0 && probeNo< NUM_SEQ_SAMPLES);
if(hss->openTCPPort == (unsigned long)-1) return;
if(hss->openTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
tcpPortBase + NUM_SEQ_SAMPLES + probeNo, hss->openTCPPort, tcpSeqBase,
tcpAck, 0, TH_SYN, prbWindowSz[probeNo], 0, prbOpts[probeNo].val, prbOpts[probeNo].len, NULL, 0);
tcpPortBase + NUM_SEQ_SAMPLES + probeNo,
hss->openTCPPort, tcpSeqBase, tcpAck, 0, TH_SYN,
prbWindowSz[probeNo], 0, prbOpts[probeNo].val,
prbOpts[probeNo].len, NULL, 0);
}
void HostOsScan::sendTEcnProbe(HostOsScanStats *hss) {
assert(hss);
if(hss->openTCPPort == (unsigned long)-1) return;
if(hss->openTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
tcpPortBase + NUM_SEQ_SAMPLES + 6, hss->openTCPPort, tcpSeqBase, 0, 8,
TH_CWR|TH_ECE|TH_SYN, prbWindowSz[6], 63477, prbOpts[6].val, prbOpts[6].len, NULL, 0);
tcpPortBase + NUM_SEQ_SAMPLES + 6, hss->openTCPPort,
tcpSeqBase, 0, 8, TH_CWR|TH_ECE|TH_SYN, prbWindowSz[6],
63477, prbOpts[6].val, prbOpts[6].len, NULL, 0);
}
void HostOsScan::sendT1_7Probe(HostOsScanStats *hss, int probeNo) {
@@ -1294,51 +1297,51 @@ void HostOsScan::sendT1_7Probe(HostOsScanStats *hss, int probeNo) {
switch(probeNo) {
case 0: /* T1 */
if(hss->openTCPPort == (unsigned long)-1) return;
if(hss->openTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
port_base, hss->openTCPPort, tcpSeqBase, tcpAck, 0,
TH_SYN, prbWindowSz[0], 0, prbOpts[0].val,
prbOpts[0].len, NULL, 0);
break;
case 1: /* T2 */
if(hss->openTCPPort == (unsigned long)-1) return;
if(hss->openTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, true,
port_base + 1, hss->openTCPPort, tcpSeqBase, tcpAck, 0,
0, prbWindowSz[7], 0, prbOpts[7].val, prbOpts[7].len, NULL, 0);
break;
case 2: /* T3 */
if(hss->openTCPPort == (unsigned long)-1) return;
if(hss->openTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
port_base + 2, hss->openTCPPort, tcpSeqBase, tcpAck, 0,
TH_SYN|TH_FIN|TH_URG|TH_PUSH, prbWindowSz[8], 0,
prbOpts[8].val, prbOpts[8].len, NULL, 0);
break;
case 3: /* T4 */
if(hss->openTCPPort == (unsigned long)-1) return;
if(hss->openTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, true,
port_base + 3, hss->openTCPPort, tcpSeqBase, tcpAck, 0,
TH_ACK, prbWindowSz[9], 0, prbOpts[9].val,
prbOpts[9].len, NULL, 0);
break;
case 4: /* T5 */
if(hss->closedTCPPort == (unsigned long)-1) return;
if(hss->closedTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
port_base + 4, hss->closedTCPPort, tcpSeqBase, tcpAck, 0,
TH_SYN, prbWindowSz[10], 0, prbOpts[10].val,
port_base + 4, hss->closedTCPPort, tcpSeqBase, tcpAck,
0, TH_SYN, prbWindowSz[10], 0, prbOpts[10].val,
prbOpts[10].len, NULL, 0);
break;
case 5: /* T6 */
if(hss->closedTCPPort == (unsigned long)-1) return;
if(hss->closedTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, true,
port_base + 5, hss->closedTCPPort, tcpSeqBase, tcpAck, 0,
TH_ACK, prbWindowSz[11], 0, prbOpts[11].val,
port_base + 5, hss->closedTCPPort, tcpSeqBase, tcpAck,
0, TH_ACK, prbWindowSz[11], 0, prbOpts[11].val,
prbOpts[11].len, NULL, 0);
break;
case 6: /* T7 */
if(hss->closedTCPPort == (unsigned long)-1) return;
if(hss->closedTCPPort == -1) return;
send_tcp_raw_decoys(rawsd, ethptr, hss->target->v4hostip(), o.ttl, false,
port_base + 6, hss->closedTCPPort, tcpSeqBase, tcpAck, 0,
TH_FIN|TH_PUSH|TH_URG, prbWindowSz[12], 0,
port_base + 6, hss->closedTCPPort, tcpSeqBase, tcpAck,
0, TH_FIN|TH_PUSH|TH_URG, prbWindowSz[12], 0,
prbOpts[12].val, prbOpts[12].len, NULL, 0);
break;
}
@@ -1360,7 +1363,7 @@ void HostOsScan::sendTIcmpProbe(HostOsScanStats *hss, int probeNo) {
void HostOsScan::sendTUdpProbe(HostOsScanStats *hss, int probeNo) {
assert(hss);
if(hss->closedUDPPort == (unsigned long)-1) return;
if(hss->closedUDPPort == -1) return;
send_closedudp_probe_2(hss->upi, rawsd, ethptr, hss->target->v4hostip(),
this->udpttl, udpPortBase + probeNo,
hss->closedUDPPort);
@@ -1511,7 +1514,10 @@ void HostOsScan::makeFP(HostOsScanStats *hss) {
makeTWinFP(hss);
for(i=3; i < NUM_FPTESTS; i++) {
if (!hss->FPtests[i] && ((hss->openTCPPort != (unsigned long) -1) || i > 7)) {
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 */
@@ -1976,7 +1982,7 @@ bool HostOsScan::processTSeqResp(HostOsScanStats *hss, struct ip *ip, int replyN
if ((tcp->th_flags & TH_RST)) {
if (hss->si.responses == 0) {
fprintf(stderr, "WARNING: RST from %s port %lu -- is this port really open?\n",
fprintf(stderr, "WARNING: RST from %s port %d -- is this port really open?\n",
hss->target->targetipstr(), hss->openTCPPort);
}
return false;
@@ -2476,7 +2482,7 @@ bool HostOsScan::processTUdpResp(HostOsScanStats *hss, struct ip *ip) {
checksum = *checksumptr;
if (checksum == 0)
strcpy(AVs[current_testno].value, "0");
strcpy(AVs[current_testno].value, "Z");
else {
*checksumptr = 0;
if (in_cksum((unsigned short *)ip2, 20) == checksum) {

184
tcpip.cc
View File

@@ -262,6 +262,142 @@ void PacketTrace::traceArp(pdirection pdir, const u8 *frame, u32 len,
return;
}
/* Get an ASCII information about a tcp option which is pointed by
optp, with a length of len. The result is stored in the result
buffer. The result may look like "<mss 1452,sackOK,timestamp
45848914 0,nop,wscale 7>" */
static void tcppacketoptinfo(u8 *optp, int len, char *result, int bufsize) {
assert(optp);
assert(result);
char *p, ch;
u8 *q;
int opcode;
u16 tmpshort;
u32 tmpword1, tmpword2;
p = result; *p = '\0';
q = optp;
ch = '<';
while(len > 0 && bufsize > 2) {
snprintf(p, bufsize, "%c", ch);
bufsize--;
p++;
opcode=*q++;
if (!opcode) { /* End of List */
snprintf(p, bufsize, "eol");
bufsize -= strlen(p);
p += strlen(p);
len--;
} else if (opcode == 1) { /* No Op */
snprintf(p, bufsize, "nop");
bufsize -= strlen(p);
p += strlen(p);
len--;
} else if (opcode == 2) { /* MSS */
if(len<4)
break; /* MSS has 4 bytes */
q++;
memcpy(&tmpshort, q, 2);
snprintf(p, bufsize, "mss %u", ntohs(tmpshort));
bufsize -= strlen(p);
p += strlen(p);
q += 2;
len -= 4;
} else if (opcode == 3) { /* Window Scale */
if(len<3)
break; /* Window Scale option has 3 bytes */
q++;
snprintf(p, bufsize, "wsacle %u", *q);
bufsize -= strlen(p);
p += strlen(p);
q++;
len -= 3;
} else if (opcode == 4) { /* SACK permitted */
if(len<2)
break; /* SACK permitted option has 2 bytes */
snprintf(p, bufsize, "sackOK");
bufsize -= strlen(p);
p += strlen(p);
q++;
len -= 2;
} else if (opcode == 5) { /* SACK */
int sackoptlen = *q;
if(len < sackoptlen)
break;
q++;
if((sackoptlen-2) % 8 != 0) {
snprintf(p, bufsize, "malformed sack");
bufsize -= strlen(p);
p += strlen(p);
} else {
snprintf(p, bufsize, "sack %d ", (sackoptlen-2)/8);
bufsize -= strlen(p);
p += strlen(p);
for(int i = 0; i < sackoptlen - 2; i += 8) {
memcpy(&tmpword1, q + i, 4);
memcpy(&tmpword2, q + i + 4, 4);
snprintf(p, bufsize, "{%u:%u}", tmpword1, tmpword2);
bufsize -= strlen(p);
p += strlen(p);
}
}
q += sackoptlen-2;
len -= sackoptlen;
} else if (opcode == 8) { /* Timestamp */
if(len<10)
break; /* Timestamp option has 10 bytes */
q++;
memcpy(&tmpword1, q, 4);
memcpy(&tmpword2, q+4, 4);
snprintf(p, bufsize, "timestamp %u %u", ntohl(tmpword1), ntohl(tmpword2));
bufsize -= strlen(p);
p += strlen(p);
q += 8;
len -= 10;
}
ch = ',';
}
if(len > 0) {
*result = '\0';
return;
}
snprintf(p, bufsize, ">");
}
/* Returns a buffer of ASCII information about a packet that may look
like "TCP 127.0.0.1:50923 > 127.0.0.1:3 S ttl=61 id=39516 iplen=40
seq=625950769" or "ICMP PING (0/1) ttl=61 id=39516 iplen=40".
@@ -269,7 +405,7 @@ void PacketTrace::traceArp(pdirection pdir, const u8 *frame, u32 len,
within (say) printf(). And certainly don't try to free() it! The
returned buffer is NUL-terminated */
static const char *ippackethdrinfo(const u8 *packet, u32 len) {
static char protoinfo[256];
static char protoinfo[512];
struct ip *ip = (struct ip *) packet;
struct tcphdr *tcp;
udphdr_bsd *udp;
@@ -279,7 +415,6 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
struct in_addr saddr, daddr;
int frag_off = 0, more_fragments = 0;
char fragnfo[64] = "";
char tflags[10];
if (ip->ip_v != 4)
return "BOGUS! IP Version in packet is not 4";
@@ -303,12 +438,15 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
ip->ip_ttl, ntohs(ip->ip_id), ntohs(ip->ip_len), fragnfo);
if (ip->ip_p == IPPROTO_TCP) {
char tflags[10];
char tcpinfo[64] = "";
char buf[32];
char tcpoptinfo[256] = "";
tcp = (struct tcphdr *) (packet + ip->ip_hl * 4);
if (frag_off > 8 || len < (u32) ip->ip_hl * 4 + 8)
snprintf(protoinfo, sizeof(protoinfo), "TCP %s:?? > %s:?? ?? %s (incomplete)", srchost, dsthost, ipinfo);
else if (frag_off == 8 && len >= (u32) ip->ip_hl * 4 + 8) {// we can get TCP flags and ACKn
else if (frag_off == 8) {// at least we can get TCP flags and ACKn
tcp = (struct tcphdr *)((u8 *) tcp - frag_off); // ugly?
p = tflags;
/* These are basically in tcpdump order */
@@ -326,17 +464,25 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
if (tcp->th_flags & TH_CWR) *p++ = 'C'; /* rfc 2481/3168 */
*p++ = '\0';
snprintf(protoinfo, sizeof(protoinfo), "TCP %s:?? > %s:?? %s %s %s",
srchost, dsthost, tflags, ipinfo, tcpinfo);
} else if (len < (u32) ip->ip_hl * 4 + 16) { // we can get ports an seq
if((u32) tcp->th_off * 4 > sizeof(struct tcphdr)) {
// tcp options
if(len < (u32) ip->ip_hl * 4 + (u32) tcp->th_off * 4 - frag_off) {
snprintf(tcpoptinfo, sizeof(tcpoptinfo), "option incomplete");
} else {
tcppacketoptinfo((u8*) tcp + sizeof(struct tcphdr),
tcp->th_off*4 - sizeof(struct tcphdr),
tcpoptinfo, sizeof(tcpoptinfo));
}
}
snprintf(protoinfo, sizeof(protoinfo), "TCP %s:?? > %s:?? %s %s %s %s",
srchost, dsthost, tflags, ipinfo, tcpinfo, tcpoptinfo);
} else if (len < (u32) ip->ip_hl * 4 + 16) { // we can get ports and seq
snprintf(tcpinfo, sizeof(tcpinfo), "seq=%lu (incomplete)", (unsigned long) ntohl(tcp->th_seq));
snprintf(protoinfo, sizeof(protoinfo), "TCP %s:%d > %s:%d ?? %s %s",
srchost, ntohs(tcp->th_sport), dsthost, ntohs(tcp->th_dport), ipinfo, tcpinfo);
} else if (len < (u32) ip->ip_hl * 4 + 16 && !frag_off) { // we can't get TCP flags
snprintf(protoinfo, sizeof(protoinfo), "TCP %s:%d > %s:%d ?? %s %s (incomplete)",
srchost, ntohs(tcp->th_sport), dsthost, ntohs(tcp->th_dport),
ipinfo, tcpinfo);
} else { // at least first 16 bytes of TCP header are there (everything we need)
} else { // at least first 16 bytes of TCP header are there
snprintf(tcpinfo, sizeof(tcpinfo), "seq=%lu win=%hi",
(unsigned long) ntohl(tcp->th_seq),
@@ -358,9 +504,21 @@ static const char *ippackethdrinfo(const u8 *packet, u32 len) {
if (tcp->th_flags & TH_CWR) *p++ = 'C'; /* rfc 2481/3168 */
*p++ = '\0';
snprintf(protoinfo, sizeof(protoinfo), "TCP %s:%d > %s:%d %s %s %s",
if((u32) tcp->th_off * 4 > sizeof(struct tcphdr)) {
// tcp options
if(len < (u32) ip->ip_hl * 4 + (u32) tcp->th_off * 4) {
snprintf(tcpoptinfo, sizeof(tcpoptinfo), "option incomplete");
} else {
tcppacketoptinfo((u8*) tcp + sizeof(struct tcphdr),
tcp->th_off*4 - sizeof(struct tcphdr),
tcpoptinfo, sizeof(tcpoptinfo));
}
}
snprintf(protoinfo, sizeof(protoinfo), "TCP %s:%d > %s:%d %s %s %s %s",
srchost, ntohs(tcp->th_sport), dsthost, ntohs(tcp->th_dport),
tflags, ipinfo, tcpinfo);
tflags, ipinfo, tcpinfo, tcpoptinfo);
}
} else if (ip->ip_p == IPPROTO_UDP && frag_off) {
snprintf(protoinfo, sizeof(protoinfo), "UDP %s:?? > %s:?? fragment %s (incomplete)", srchost, dsthost, ipinfo);