About to release 4.20SOC-ALPHA1

This commit is contained in:
fyodor 2006-06-25 02:02:14 +00:00
parent 05a5be9af8
commit 56384d8770
22 changed files with 436 additions and 203 deletions

View file

@ -1,5 +1,11 @@
# Nmap Changelog ($Id$); -*-text-*-
Nmap 4.20SOC-ALPHA1
o Integrated initial 2nd generation OS detection patch! The system is
documented at http://insecure.org/nmap/osdetect/ . Thanks to Zhao Lei
for helping with the coding and design.
o portlist.cc was refactored to remove some code duplication. Thanks
to Diman Todorov for the patch.

View file

@ -110,7 +110,8 @@ FingerPrintResults::FingerPrintResults() {
overall_results = OSSCAN_NOMATCHES;
memset(accuracy, 0, sizeof(accuracy));
isClassified = false;
osscan_opentcpport = osscan_closedtcpport = -1;
osscan_opentcpport = osscan_closedtcpport = osscan_closedudpport = -1;
distance = -1;
memset(FPs, 0, sizeof(FPs));
numFPs = goodFP = 0;
}
@ -139,7 +140,12 @@ bool FingerPrintResults::fingerprintSuitableForSubmission() {
if (o.scan_delay > 500) // This can screw up the sequence timing
return false;
if (osscan_opentcpport < 0 || osscan_closedtcpport < 0 ) // then results won't be complete
if (osscan_opentcpport < 0 || osscan_closedtcpport < 0 || osscan_closedudpport < 0)
/* The results won't be complete */
return false;
if (distance > 5)
/* Too far away from us. */
return false;
return true;

View file

@ -137,10 +137,14 @@ class FingerPrintResults {
any perfect (accuracy 1.0) matches, only those will be returned */
const struct OS_Classification_Results *getOSClassification();
int osscan_opentcpport; /* Open port used for scannig (if one found --
int osscan_opentcpport; /* Open TCP port used for scannig (if one found --
otherwise -1) */
int osscan_closedtcpport; /* Closed port used for scannig (if one found --
int osscan_closedtcpport; /* Closed TCP port used for scannig (if one found --
otherwise -1) */
int osscan_closedudpport; /* Closed UDP port used for scannig (if one found --
otherwise -1) */
int distance; /* How "far" is this FP gotten from? */
FingerPrint *FPs[10]; /* Fingerprint data obtained from host */
int numFPs;
int goodFP;

View file

@ -1,4 +1,4 @@
export NMAP_VERSION = 4.11
export NMAP_VERSION = 4.20SOC-ALPHA1
NMAP_NAME= Nmap
NMAP_URL= http://www.insecure.org/nmap/
NMAP_PLATFORM=@host@
@ -46,11 +46,11 @@ TARGET = nmap
TARGETNMAPFE=@TARGETNMAPFE@
INSTALLNMAPFE=@INSTALLNMAPFE@
export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_tty.cc nmap_dns.cc @COMPAT_SRCS@
export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc osscan2.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_tty.cc nmap_dns.cc @COMPAT_SRCS@
export HDRS = charpool.h FingerPrintResults.h global_structures.h idle_scan.h MACLookup.h nmap_amigaos.h nmap_dns.h nmap_error.h nmap.h NmapOps.h NmapOutputTable.h nmap_rpc.h nmap_tty.h nmap_winconfig.h osscan.h output.h portlist.h protocols.h scan_engine.h service_scan.h services.h TargetGroup.h Target.h targets.h tcpip.h timing.h utils.h
export HDRS = charpool.h FingerPrintResults.h global_structures.h idle_scan.h MACLookup.h nmap_amigaos.h nmap_dns.h nmap_error.h nmap.h NmapOps.h NmapOutputTable.h nmap_rpc.h nmap_tty.h nmap_winconfig.h osscan.h osscan2.h output.h portlist.h protocols.h scan_engine.h service_scan.h services.h TargetGroup.h Target.h targets.h tcpip.h timing.h utils.h
OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o nmap_tty.o nmap_dns.o @COMPAT_OBJS@
OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o osscan2.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o nmap_tty.o nmap_dns.o @COMPAT_OBJS@
# %.o : %.cc -- nope this is a GNU extension
.cc.o:

View file

@ -194,6 +194,7 @@ void NmapOps::Initialize() {
interactivemode = 0;
ping_group_sz = PING_GROUP_SZ;
generate_random_ips = 0;
reference_FPs1 = NULL;
reference_FPs = NULL;
magic_port = 33000 + (get_random_uint() % 31000);
magic_port_set = 0;

View file

@ -174,7 +174,8 @@ class NmapOps {
int interactivemode;
int ping_group_sz;
int generate_random_ips; /* -iR option */
FingerPrint **reference_FPs;
FingerPrint **reference_FPs1; /* Used in the old OS scan system. */
FingerPrint **reference_FPs; /* Used in the new OS scan system. */
u16 magic_port;
unsigned short magic_port_set; /* Was this set by user? */
int num_ping_synprobes;

View file

@ -120,6 +120,8 @@ Target::Target() {
void Target::Initialize() {
hostname = NULL;
memset(&seq, 0, sizeof(seq));
distance = -1;
FPR1 = NULL;
FPR = NULL;
osscan_performed = 0;
wierd_responses = flags = 0;
@ -161,8 +163,8 @@ void Target::FreeInternal() {
nameIPBuf = NULL;
}
if (FPR1) delete FPR1;
if (FPR) delete FPR;
}
/* Creates a "presentation" formatted string out of the IPv4/IPv6 address.

View file

@ -215,7 +215,9 @@ class Target {
const char *deviceFullName() { return *devfullname? devfullname : NULL; }
struct seq_info seq;
FingerPrintResults *FPR;
int distance;
FingerPrintResults *FPR1; /* FP results get by the old OS scan system. */
FingerPrintResults *FPR; /* FP results get by the new OS scan system. */
int osscan_performed; /* nonzero if an osscan was performed */
PortList ports;
/*

View file

@ -605,6 +605,16 @@
</xsl:template>
<!-- ............................................................ -->
<!-- distance -->
<!-- ............................................................ -->
<xsl:template match="distance">
<xsl:if test="@value != ''"><h3>network distance</h3></xsl:if>
<ul>
<li>distance: <xsl:value-of select="@value" /> hops</li>
</ul>
</xsl:template>
<!-- ............................................................ -->
<!-- smurf -->
<!-- ............................................................ -->
<xsl:template match="smurf">

View file

@ -216,6 +216,12 @@ struct seq_info {
time_t lastboot; /* 0 means unknown */
};
/* Different kinds of Ipids. */
struct ipid_info {
int tcp_ipids[NUM_SEQ_SAMPLES];
int icmp_ipids[NUM_SEQ_SAMPLES];
};
/* The various kinds of port/protocol scans we can have
* Each element is to point to an array of port/protocol numbers
*/

View file

@ -187,10 +187,10 @@ static int ipid_proxy_probe(struct idle_proxy_info *proxy, int *probes_sent,
/* Time to send the pr0be!*/
send_tcp_raw(proxy->rawsd, proxy->ethptr, proxy->host.v4sourceip(),
proxy->host.v4hostip(), o.ttl, base_port + tries,
proxy->host.v4hostip(), o.ttl, false, base_port + tries,
proxy->probe_port,
seq_base + (packet_send_count++ * 500) + 1, ack,
TH_SYN|TH_ACK, 0,
seq_base + (packet_send_count++ * 500) + 1, ack, 0,
TH_SYN|TH_ACK, 0, 0,
(u8 *) "\x02\x04\x05\xb4", 4, NULL, 0);
sent++;
tries++;
@ -417,10 +417,10 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
think I'll use TH_SYN, although it is a tough call. */
/* We can't use decoys 'cause that would screw up the IPIDs */
send_tcp_raw(proxy->rawsd, proxy->ethptr, proxy->host.v4sourceip(),
proxy->host.v4hostip(), o.ttl,
proxy->host.v4hostip(), o.ttl, false,
o.magic_port + probes_sent + 1, proxy->probe_port,
sequence_base + probes_sent + 1, ack, TH_SYN|TH_ACK,
0, (u8 *) "\x02\x04\x05\xb4", 4, NULL, 0);
sequence_base + probes_sent + 1, ack, 0, TH_SYN|TH_ACK,
0, 0, (u8 *) "\x02\x04\x05\xb4", 4, NULL, 0);
gettimeofday(&probe_send_times[probes_sent], NULL);
probes_sent++;
@ -525,9 +525,9 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
if (probes_sent) usleep(50000);
send_tcp_raw(proxy->rawsd, proxy->ethptr, first_target,
proxy->host.v4hostip(),
o.ttl, o.magic_port, proxy->probe_port,
sequence_base + probes_sent + 1, 0, TH_SYN|TH_ACK,
ack, (u8 *) "\x02\x04\x05\xb4", 4, NULL, 0);
o.ttl, false,o.magic_port, proxy->probe_port,
sequence_base + probes_sent + 1, ack, 0, TH_SYN|TH_ACK,
0, 0, (u8 *) "\x02\x04\x05\xb4", 4, NULL, 0);
}
@ -682,7 +682,7 @@ static int idlescan_countopen2(struct idle_proxy_info *proxy,
about this more. */
send_tcp_raw(proxy->rawsd, eth.ethsd? &eth : NULL, proxy->host.v4hostip(),
target->v4hostip(),
o.ttl, proxy->probe_port, ports[pr0be], seq, 0, TH_SYN, 0,
o.ttl, false, proxy->probe_port, ports[pr0be], seq, 0, 0, TH_SYN, 0, 0,
(u8 *) "\x02\x04\x05\xb4", 4, o.extra_payload, o.extra_payload_length);
}
gettimeofday(&end, NULL);

30
nmap.cc
View file

@ -102,6 +102,7 @@
#include "nmap.h"
#include "osscan.h"
#include "osscan2.h"
#include "scan_engine.h"
#include "idle_scan.h"
#include "timing.h"
@ -594,7 +595,7 @@ int nmap_main(int argc, char *argv[]) {
/* OK, lets parse these args! */
optind = 1; /* so it can be called multiple times */
while((arg = getopt_long_only(argc,fakeargv,"6Ab:D:d::e:Ffg:hIi:M:m:nOo:P:p:qRrS:s:T:Vv", long_options, &option_index)) != EOF) {
while((arg = getopt_long_only(argc,fakeargv,"6Ab:D:d::e:Ffg:hIi:M:m:nO::o:P:p:qRrS:s:T:Vv", long_options, &option_index)) != EOF) {
switch(arg) {
case 0:
if (optcmp(long_options[option_index].name, "max-rtt-timeout") == 0) {
@ -797,7 +798,7 @@ int nmap_main(int argc, char *argv[]) {
case 'A':
o.servicescan = true;
if (o.isr00t)
o.osscan++;
o.osscan = OS_SCAN_DEFAULT;
break;
case 'b':
o.bouncescan++;
@ -876,7 +877,15 @@ int nmap_main(int argc, char *argv[]) {
break;
case 'n': o.noresolve++; break;
case 'O':
o.osscan++;
if (!optarg)
o.osscan = OS_SCAN_DEFAULT;
else if (*optarg == '1')
o.osscan = OS_SCAN_SYS_1_ONLY;
else if (*optarg == '2')
o.osscan = OS_SCAN_SYS_2_ONLY;
else {
fatal("Use -O for new osscan engine, -O1 for old osscan engine.");
}
break;
case 'o':
normalfilename = optarg;
@ -1076,8 +1085,10 @@ int nmap_main(int argc, char *argv[]) {
if (pre_host_timeout != -1) o.host_timeout = pre_host_timeout;
if (o.osscan)
o.reference_FPs = parse_fingerprint_reference_file();
if (o.osscan == OS_SCAN_SYS_1_ONLY)
o.reference_FPs1 = parse_fingerprint_reference_file("nmap-os-fingerprints");
else
o.reference_FPs = parse_fingerprint_reference_file("nmap-os-db");
o.ValidateOptions();
@ -1548,6 +1559,9 @@ int nmap_main(int argc, char *argv[]) {
service_scan(Targets);
}
if (o.osscan != OS_SCAN_SYS_1_ONLY)
os_scan_2(Targets);
for(targetno = 0; targetno < Targets.size(); targetno++) {
currenths = Targets[targetno];
@ -1558,7 +1572,7 @@ int nmap_main(int argc, char *argv[]) {
if (o.servicescan || o.rpcscan) pos_scan(currenths, NULL, 0, RPC_SCAN);
// Should be host parallelized. Though rarely takes a huge amt. of time.
if (o.osscan) {
if (o.osscan == OS_SCAN_SYS_1_ONLY) {
os_scan(currenths);
}
@ -1980,6 +1994,10 @@ char *ipidclass2ascii(int seqclass) {
return "Random positive increments";
case IPID_SEQ_ZERO:
return "All zeros";
case IPID_SEQ_LINUX:
return "Linux way";
case IPID_SEQ_VBP:
return "Different counters by <src, dest, protocol>";
case IPID_SEQ_UNKNOWN:
return "Busy server or unknown class";
default:

26
nmap.h
View file

@ -275,8 +275,6 @@ void *realloc();
/* If reads of a UDP port keep returning EAGAIN (errno 13), do we want to
count the port as valid? */
#define RISKY_UDP_SCAN 0
/* How many syn packets do we send to TCP sequence a host? */
#define NUM_SEQ_SAMPLES 6
/* This ideally should be a port that isn't in use for any protocol on our machine or on the target */
#define MAGIC_PORT 49724
/* How many udp sends without a ICMP port unreachable error does it take before we consider the port open? */
@ -366,6 +364,19 @@ void *realloc();
#define PINGTYPE_ARP 1024
#define DEFAULT_PING_TYPES PINGTYPE_TCP|PINGTYPE_TCP_USE_ACK|PINGTYPE_ICMP_PING
/* OS scan */
#define OS_SCAN_DEFAULT 9
#define OS_SCAN_SYS_1_ONLY 1
#define OS_SCAN_SYS_2_ONLY 2
/* How many syn packets do we send to TCP sequence a host? */
#define NUM_SEQ_SAMPLES 6
/* The max length of each line of the subject fingerprint when
wrapped. */
#define FP_RESULT_WRAP_LINE_LEN 74
/* TCP/IP ISN sequence prediction classes */
#define SEQ_UNKNOWN 0
#define SEQ_64K 1
@ -381,7 +392,8 @@ void *realloc();
#define TS_SEQ_2HZ 2
#define TS_SEQ_100HZ 3
#define TS_SEQ_1000HZ 4
#define TS_SEQ_UNSUPPORTED 5 /* System didn't send back a timestamp */
#define TS_SEQ_OTHER_NUM 5
#define TS_SEQ_UNSUPPORTED 6 /* System didn't send back a timestamp */
#define IPID_SEQ_UNKNOWN 0
#define IPID_SEQ_INCR 1 /* simple increment by one each time */
@ -392,6 +404,14 @@ void *realloc();
#define IPID_SEQ_RD 4 /* Appears to select IPID using a "random" distributions (meaning it can go up or down) */
#define IPID_SEQ_CONSTANT 5 /* Contains 1 or more sequential duplicates */
#define IPID_SEQ_ZERO 6 /* Every packet that comes back has an IP.ID of 0 (eg Linux 2.4 does this) */
#define IPID_SEQ_LINUX 7 /* Different IPID counter in different TCP
session but set zero in the TCP
negotiation process. And different IPID
counter in different protocol. Found in
linux 2.6. */
#define IPID_SEQ_VBP 8 /* Different IPID counter for different <host,
dest, protocol> triple. */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif

View file

@ -106,7 +106,7 @@
/* Without this, Windows will give us all sorts of crap about using functions
like strcpy() even if they are done safely */
#define _CRT_SECURE_NO_DEPRECATE 1
#define NMAP_VERSION "4.11"
#define NMAP_VERSION "4.20SOC-ALPHA1"
#define NMAP_NAME "Nmap"
#define NMAP_URL "http://www.insecure.org/nmap"
#define NMAP_PLATFORM "i686-pc-windows-windows"

201
osscan.cc
View file

@ -578,18 +578,19 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
/* Lets find an open port to use */
openport = (unsigned long) -1;
target->FPR->osscan_opentcpport = -1;
target->FPR->osscan_closedtcpport = -1;
target->FPR1->osscan_opentcpport = -1;
target->FPR1->osscan_closedtcpport = -1;
target->FPR1->osscan_closedudpport = -1;
tport = NULL;
if ((tport = target->ports.nextPort(NULL, IPPROTO_TCP, PORT_OPEN))) {
openport = tport->portno;
target->FPR->osscan_opentcpport = tport->portno;
target->FPR1->osscan_opentcpport = tport->portno;
}
/* Now we should find a closed port */
if ((tport = target->ports.nextPort(NULL, IPPROTO_TCP, PORT_CLOSED))) {
closedport = tport->portno;
target->FPR->osscan_closedtcpport = tport->portno;
target->FPR1->osscan_closedtcpport = tport->portno;
} else if ((tport = target->ports.nextPort(NULL, IPPROTO_TCP, PORT_UNFILTERED))) {
/* Well, we will settle for unfiltered */
closedport = tport->portno;
@ -612,57 +613,58 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
/* Test 1 */
if (!FPtests[1]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port, openport, sequence_base, 0,
TH_ECE|TH_SYN, 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);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
current_port, openport, sequence_base, 0, 0,
TH_ECE|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);
}
/* Test 2 */
if (!FPtests[2]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +1,
openport, sequence_base, 0,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);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
current_port +1, openport, sequence_base, 0, 0,
0, 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);
}
/* Test 3 */
if (!FPtests[3]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, current_port +2,
openport, sequence_base, 0,TH_SYN|TH_FIN|TH_URG|TH_PUSH, 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);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
current_port +2, openport, sequence_base, 0, 0,
TH_SYN|TH_FIN|TH_URG|TH_PUSH, 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);
}
/* Test 4 */
if (!FPtests[4]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +3,
openport, sequence_base, 0,TH_ACK, 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);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
current_port +3, openport, sequence_base, 0, 0,
TH_ACK, 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);
}
}
/* Test 5 */
if (!FPtests[5]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +4,
closedport, sequence_base, 0,TH_SYN, 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);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
current_port +4, closedport, sequence_base, 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);
}
/* Test 6 */
if (!FPtests[6]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +5,
closedport, sequence_base, 0,TH_ACK, 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);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
current_port +5, closedport, sequence_base, 0, 0,
TH_ACK, 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);
}
/* Test 7 */
if (!FPtests[7]) {
if (o.scan_delay) enforce_scan_delay(NULL);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
current_port +6,
closedport, sequence_base, 0,TH_FIN|TH_PUSH|TH_URG, 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);
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
current_port +6, closedport, sequence_base, 0, 0,
TH_FIN|TH_PUSH|TH_URG, 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);
}
/* Test 8 */
@ -747,11 +749,11 @@ static FingerPrint *get_fingerprint(Target *target, struct seq_info *si) {
usleep(remaining_us);
}
}
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl,
send_tcp_raw_decoys(rawsd, ethptr, target->v4hostip(), o.ttl, false,
o.magic_port + seq_packets_sent + 1,
openport,
sequence_base + seq_packets_sent + 1, 0,
TH_SYN, 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);
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++;
@ -1183,9 +1185,9 @@ static struct AVal *gettestbyname(FingerPrint *FP, const char *name) {
static int AVal_match(struct AVal *reference, struct AVal *fprint, unsigned long *num_subtests, unsigned long *num_subtests_succeeded, int shortcut) {
struct AVal *current_ref;
struct AVal *current_fp;
unsigned int number;
unsigned int number, number1;
unsigned int val;
char *p, *q; /* OHHHH YEEEAAAAAHHHH!#!@#$!% */
char *p, *q, *q1; /* OHHHH YEEEAAAAAHHHH!#!@#$!% */
char valcpy[512];
char *endptr;
int andexp, orexp, expchar, numtrue;
@ -1196,9 +1198,9 @@ static int AVal_match(struct AVal *reference, struct AVal *fprint, unsigned long
current_fp = getattrbyname(fprint, current_ref->attribute);
if (!current_fp) continue;
/* OK, we compare an attribute value in current_fp->value to a
potentially large expression in current_ref->value. The syntax uses
< (less than), > (greather than), + (non-zero), | (or), and & (and)
No parenthesis are allowed and an expression cannot have | AND & */
potentially large expression in current_ref->value. The syntax
uses < (less than), > (greather than), + (non-zero), | (or), -
(range), and & (and). No parenthesis are allowed */
numtrue = andexp = orexp = 0; testfailed = 0;
Strncpy(valcpy, current_ref->value, sizeof(valcpy));
p = valcpy;
@ -1229,8 +1231,17 @@ static int AVal_match(struct AVal *reference, struct AVal *fprint, unsigned long
val = strtol(current_fp->value, &endptr, 16);
if (val <= number || *endptr) { if (andexp) { testfailed=1; break; } }
else { numtrue++; if (orexp) break; }
} else if (((q1 = strchr(p, '-')) != NULL) && isxdigit((int) p[0]) && isxdigit((int) q1[1])) {
if (!*current_fp->value) { if (andexp) { testfailed=1; break; } }
*q1 = '\0'; number = strtol(p, NULL, 16);
number1 = strtol(q1 + 1, NULL, 16);
if(number1 < number && o.debugging) {
error("Range error in reference aval: %s=%s\n", current_ref->attribute, current_ref->value);
}
else {
val = strtol(current_fp->value, &endptr, 16);
if (val < number || val > number1 || *endptr) { if (andexp) { testfailed=1; break; } }
else { numtrue++; if (orexp) break; }
} else {
if (strcmp(p, current_fp->value))
{ if (andexp) { testfailed=1; break; } }
else { numtrue++; if (orexp) break; }
@ -1322,7 +1333,7 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
acc = compare_fingerprints(current_os, FP, 0);
/* error("Comp to %s: %li/%li=%f", o.reference_FPs[i]->OS_name, num_subtests_succeeded, num_subtests, acc); */
/* error("Comp to %s: %li/%li=%f", o.reference_FPs1[i]->OS_name, num_subtests_succeeded, num_subtests, acc); */
if (acc >= FPR_entrance_requirement || acc == 1.0) {
state = 0;
@ -1441,8 +1452,8 @@ o.current_scantype = OS_SCAN;
log_write(LOG_STDOUT|LOG_NORMAL|LOG_SKID, "Initiating OS Detection against %s at %.3fs\n", target->targetipstr(), starttimems / 1000.0);
}
if (target->FPR == NULL)
target->FPR = new FingerPrintResults;
if (target->FPR1 == NULL)
target->FPR1 = new FingerPrintResults;
memset(si, 0, sizeof(si));
if (target->ports.getStateCounts(IPPROTO_TCP, PORT_OPEN) == 0 ||
@ -1467,10 +1478,10 @@ o.current_scantype = OS_SCAN;
// Do nothing because the keyWasPressed Method prints out the basic status line
}
target->FPR->FPs[itry] = get_fingerprint(target, &si[itry]);
target->FPR1->FPs[itry] = get_fingerprint(target, &si[itry]);
match_fingerprint(target->FPR->FPs[itry], &FP_matches[itry],
o.reference_FPs, OSSCAN_GUESS_THRESHOLD);
match_fingerprint(target->FPR1->FPs[itry], &FP_matches[itry],
o.reference_FPs1, OSSCAN_GUESS_THRESHOLD);
if (FP_matches[itry].overall_results == OSSCAN_SUCCESS &&
FP_matches[itry].num_perfect_matches > 0)
break;
@ -1478,13 +1489,13 @@ o.current_scantype = OS_SCAN;
sleep(2);
}
target->FPR->numFPs = (itry == 3)? 3 : itry + 1;
memcpy(&(target->seq), &si[target->FPR->numFPs - 1], sizeof(struct seq_info));
target->FPR1->numFPs = (itry == 3)? 3 : itry + 1;
memcpy(&(target->seq), &si[target->FPR1->numFPs - 1], sizeof(struct seq_info));
/* Now lets find the best match */
bestacc = 0;
bestaccidx = 0;
for(itry=0; itry < target->FPR->numFPs; itry++) {
for(itry=0; itry < target->FPR1->numFPs; itry++) {
if (FP_matches[itry].overall_results == OSSCAN_SUCCESS &&
FP_matches[itry].num_matches > 0 &&
FP_matches[itry].accuracy[0] > bestacc) {
@ -1496,27 +1507,27 @@ o.current_scantype = OS_SCAN;
}
for(i=0; i < target->FPR->numFPs; i++) {
for(i=0; i < target->FPR1->numFPs; i++) {
if (i == bestaccidx)
continue;
if (o.debugging) {
error("Failed exact match #%d (0-based):\n%s", i, fp2ascii(target->FPR->FPs[i]));
error("Failed exact match #%d (0-based):\n%s", i, fp2ascii(target->FPR1->FPs[i]));
}
}
if (target->FPR->numFPs > 1 && target->FPR->overall_results == OSSCAN_SUCCESS &&
target->FPR->accuracy[0] == 1.0) {
if (o.verbose) error("WARNING: OS didn't match until the try #%d", target->FPR->numFPs);
if (target->FPR1->numFPs > 1 && target->FPR1->overall_results == OSSCAN_SUCCESS &&
target->FPR1->accuracy[0] == 1.0) {
if (o.verbose) error("WARNING: OS didn't match until the try #%d", target->FPR1->numFPs);
}
target->FPR->goodFP = bestaccidx;
target->FPR1->goodFP = bestaccidx;
// Now we redo the match, since target->FPR has various data (such as
// target->FPR->numFPs) which is not in FP_matches[bestaccidx]. This is
// Now we redo the match, since target->FPR1 has various data (such as
// target->FPR1->numFPs) which is not in FP_matches[bestaccidx]. This is
// kinda ugly.
if (target->FPR->goodFP >= 0)
match_fingerprint(target->FPR->FPs[target->FPR->goodFP], target->FPR,
o.reference_FPs, OSSCAN_GUESS_THRESHOLD);
if (target->FPR1->goodFP >= 0)
match_fingerprint(target->FPR1->FPs[target->FPR1->goodFP], target->FPR1,
o.reference_FPs1, OSSCAN_GUESS_THRESHOLD);
if (o.debugging > 2) {
log_write(LOG_STDOUT|LOG_NORMAL|LOG_SKID, "Completed OS Detection against %s at %.3fs (took %.3fs)\n", target->targetipstr(), o.TimeSinceStartMS() / 1000.0, (o.TimeSinceStartMS() - starttimems) / 1000.0);
@ -1529,34 +1540,55 @@ o.current_scantype = OS_SCAN;
top of a fingerprint. Gives info which might be useful when the
FPrint is submitted (eg Nmap version, etc). Result is written (up
to ostrlen) to the ostr var passed in */
static void WriteSInfo(char *ostr, int ostrlen, int openport, int closedport,
const u8 *mac) {
static void WriteSInfo(char *ostr, int ostrlen, bool isGoodFP,
const struct in_addr * const addr, int distance, const u8 *mac,
int openTcpPort, int closedTcpPort, int closedUdpPort) {
struct tm *ltime;
time_t timep;
char dsbuf[8], otbuf[8], ctbuf[8], cubuf[8];
char macbuf[16];
timep = time(NULL);
ltime = localtime(&timep);
otbuf[0] = '\0';
if(openTcpPort != -1)
snprintf(otbuf, sizeof(otbuf), "%d", openTcpPort);
ctbuf[0] = '\0';
if(closedTcpPort != -1)
snprintf(ctbuf, sizeof(ctbuf), "%d", closedTcpPort);
cubuf[0] = '\0';
if(closedUdpPort != -1)
snprintf(cubuf, sizeof(cubuf), "%d", closedUdpPort);
dsbuf[0] = '\0';
if(distance != -1) {
snprintf(dsbuf, sizeof(dsbuf), "%%DS=%d", distance);
}
macbuf[0] = '\0';
if (mac)
snprintf(macbuf, sizeof(macbuf), "%%M=%02X%02X%02X", mac[0], mac[1],
mac[2]);
snprintf(macbuf, sizeof(macbuf), "%%M=%02X%02X%02X", mac[0], mac[1], mac[2]);
snprintf(ostr, ostrlen, "SInfo(V=%s%%P=%s%%D=%d/%d%%Tm=%X%%O=%d%%C=%d%s)\n",
NMAP_VERSION, NMAP_PLATFORM, ltime->tm_mon + 1, ltime->tm_mday,
(int) timep, openport, closedport, macbuf);
snprintf(ostr, ostrlen, "SCAN(V=%s%%D=%d/%d%%OT=%s%%CT=%s%%CU=%s%%PV=%c%s%%G=%c%s%%TM=%X%%P=%s)",
NMAP_VERSION, ltime->tm_mon + 1, ltime->tm_mday,
otbuf, ctbuf, cubuf, isipprivate(addr)?'Y':'N', dsbuf, isGoodFP?'Y':'N',
macbuf, (int) timep, NMAP_PLATFORM);
}
char *mergeFPs(FingerPrint *FPs[], int numFPs, int openport, int closedport,
const u8 *mac) {
char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP,
const struct in_addr * const addr, int distance, const u8 *mac,
int openTcpPort, int closedTcpPort, int closedUdpPort, bool wrapit) {
static char str[10240];
static char wrapstr[10240];
struct AVal *AV;
FingerPrint *currentFPs[32];
char *p = str;
int i;
int changed;
char *end = str + sizeof(str) - 1; /* Last byte allowed to write into */
if (numFPs <=0) return "(None)";
if (numFPs > 32) return "(Too many)";
@ -1568,9 +1600,10 @@ for(i=0; i < numFPs; i++) {
currentFPs[i] = FPs[i];
}
/* Lets start by writing the fake "Info" test for submitting fingerprints */
WriteSInfo(str, sizeof(str), openport, closedport, mac);
/* Lets start by writing the fake "SCAN" test for submitting fingerprints */
WriteSInfo(str, sizeof(str), isGoodFP, addr, distance, mac, openTcpPort, closedTcpPort, closedUdpPort);
p = p + strlen(str);
if (!wrapit) *p++ = '\n';
do {
changed = 0;
@ -1599,6 +1632,8 @@ do {
if(*(p-1) != '(')
p--; /* Kill the final & */
*p++ = ')';
if(!wrapit)
*p++ = '\n';
}
/* Now prepare for the next one */
@ -1608,9 +1643,34 @@ do {
} while(changed);
*p = '\0';
return str;
}
if(!wrapit) {
return str;
} else {
/* Wrap the str. */
int len;
char *p1 = wrapstr;
end = wrapstr + sizeof(wrapstr) - 1;
p = str;
while(*p && end-p1 >= 3) {
len = 0;
strcpy(p1, "OS:"); p1 += 3; len +=3;
while(*p && len <= FP_RESULT_WRAP_LINE_LEN && end-p1 > 0) {
*p1++=*p++; len++;
}
if(end-p1<=0) {
fatal("Wrapped result too long!\n");
break;
}
*p1++ = '\n';
}
*p1 = '\0';
return wrapstr;
}
}
char *fp2ascii(FingerPrint *FP) {
static char str[2048];
@ -1953,18 +2013,17 @@ while(fgets(line, sizeof(line), fp)) {
/* printf("Read in fingerprint:\n%s\n", fp2ascii(FPs[numrecords])); */
numrecords++;
if (numrecords >= max_records)
fatal("Too many OS fingerprints -- 0verfl0w");
fatal("Too many OS fingerprints -- 0verflow");
}
fclose(fp);
FPs[numrecords] = NULL;
return FPs;
}
FingerPrint **parse_fingerprint_reference_file() {
FingerPrint **parse_fingerprint_reference_file(char *dbname) {
char filename[256];
if (nmap_fetchfile(filename, sizeof(filename), "nmap-os-fingerprints") == -1){
fatal("OS scan requested but I cannot find nmap-os-fingerprints file. It should be in %s, ~/.nmap/ or .", NMAPDATADIR);
if (nmap_fetchfile(filename, sizeof(filename), dbname) == -1){
fatal("OS scan requested but I cannot find %s file. It should be in %s, ~/.nmap/ or .", dbname, NMAPDATADIR);
}
return parse_fingerprint_file(filename);

View file

@ -129,7 +129,7 @@ char *fp2ascii(FingerPrint *FP);
which some partial fingerpritns are OK. */
FingerPrint *parse_single_fingerprint(char *fprint_orig);
FingerPrint **parse_fingerprint_file(char *fname);
FingerPrint **parse_fingerprint_reference_file();
FingerPrint **parse_fingerprint_reference_file(char *dbname);
/* Compares 2 fingerprints -- a referenceFP (can have expression
attributes) with an observed fingerprint (no expressions). If
@ -150,8 +150,7 @@ void match_fingerprint(FingerPrint *FP, FingerPrintResults *FPR,
/* Returns true if perfect match -- if num_subtests & num_subtests_succeeded are non_null it updates them. if shortcircuit is zero, it does all the tests, otherwise it returns when the first one fails */
void freeFingerPrint(FingerPrint *FP);
char *mergeFPs(FingerPrint *FPs[], int numFPs, int openport, int closedport,
const u8 *mac);
char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP, const struct in_addr * const addr, int distance, const u8 *mac, int openTcpPort, int closedTcpPort, int closedUdpPort, bool wrapit);
/* This function takes an array of "numSamples" IP IDs and analyzes
them to determine their sequenceability classification. It returns

178
output.cc
View file

@ -1208,120 +1208,184 @@ void printmacinfo(Target *currenths) {
/* Prints the formatted OS Scan output to stdout, logfiles, etc (but only
if an OS Scan was performed */
if an OS Scan was performed).*/
void printosscanoutput(Target *currenths) {
int i;
char numlst[512]; /* For creating lists of numbers */
char *p; /* Used in manipulating numlst above */
FingerPrintResults *FPR;
int distance = -1;
bool wrapFP = true; /* Whether to wrap the fingerprint result. */
if (!currenths->osscan_performed)
return;
if (currenths->FPR == NULL && currenths->FPR1 == NULL) {
return;
} else if (currenths->FPR != NULL && currenths->FPR1 == NULL) {
FPR = currenths->FPR;
} else if (currenths->FPR == NULL && currenths->FPR1 != NULL) {
FPR = currenths->FPR1;
wrapFP = false;
}
else {
/* Neither is NULL. This happens when new OS scan system fails to
get a perfect match and falls back on the old OS scan
system. */
if (currenths->FPR->num_perfect_matches > 0) {
FPR = currenths->FPR; /* Just an ensurance. */
} else if (currenths->FPR1->num_perfect_matches > 0) {
FPR = currenths->FPR1;
wrapFP = false;
} else if (currenths->FPR->overall_results == OSSCAN_SUCCESS) {
FPR = currenths->FPR;
} else if (currenths->FPR1->overall_results == OSSCAN_SUCCESS) {
FPR = currenths->FPR1;
wrapFP = false;
} else {
/* Both fails. */
FPR = currenths->FPR;
}
}
if (islocalhost(currenths->v4hostip())) {
/* scanning localhost */
distance = 0;
} else if (currenths->MACAddress()) {
/* on the same network segment */
distance = 1;
} else if (currenths->distance!=-1) {
distance = currenths->distance;
}
if (currenths->osscan_performed && currenths->FPR != NULL) {
log_write(LOG_XML, "<os>");
if (currenths->FPR->osscan_opentcpport > 0) {
if (FPR->osscan_opentcpport > 0) {
log_write(LOG_XML,
"<portused state=\"open\" proto=\"tcp\" portid=\"%hu\" />\n",
currenths->FPR->osscan_opentcpport);
FPR->osscan_opentcpport);
}
if (currenths->FPR->osscan_closedtcpport > 0) {
if (FPR->osscan_closedtcpport > 0) {
log_write(LOG_XML,
"<portused state=\"closed\" proto=\"tcp\" portid=\"%hu\" />\n",
currenths->FPR->osscan_closedtcpport);
FPR->osscan_closedtcpport);
}
if (FPR->osscan_closedudpport > 0) {
log_write(LOG_XML,
"<portused state=\"closed\" proto=\"udp\" portid=\"%hu\" />\n",
FPR->osscan_closedudpport);
}
// If the FP can't be submitted anyway, might as well make a guess.
printosclassificationoutput(currenths->FPR->getOSClassification(),
o.osscan_guess || !currenths->FPR->fingerprintSuitableForSubmission());
printosclassificationoutput(FPR->getOSClassification(),
o.osscan_guess || !FPR->fingerprintSuitableForSubmission());
if (currenths->FPR->overall_results == OSSCAN_SUCCESS && (currenths->FPR->num_perfect_matches <= 8 || o.debugging)) {
if (currenths->FPR->num_perfect_matches > 0) {
if (FPR->overall_results == OSSCAN_SUCCESS && (FPR->num_perfect_matches <= 8 || o.debugging)) {
if (FPR->num_perfect_matches > 0) {
char *p;
log_write(LOG_MACHINE,"\tOS: %s", currenths->FPR->prints[0]->OS_name);
log_write(LOG_MACHINE,"\tOS: %s", FPR->prints[0]->OS_name);
log_write(LOG_XML, "<osmatch name=\"%s\" accuracy=\"100\" line=\"%d\" />\n",
p = xml_convert(currenths->FPR->prints[0]->OS_name),
currenths->FPR->prints[0]->line);
p = xml_convert(FPR->prints[0]->OS_name),
FPR->prints[0]->line);
free(p);
i = 1;
while(currenths->FPR->accuracy[i] == 1 ) {
log_write(LOG_MACHINE,"|%s", currenths->FPR->prints[i]->OS_name);
while(FPR->accuracy[i] == 1 ) {
log_write(LOG_MACHINE,"|%s", FPR->prints[i]->OS_name);
log_write(LOG_XML, "<osmatch name=\"%s\" accuracy=\"100\" line=\"%d\" />\n",
p = xml_convert(currenths->FPR->prints[i]->OS_name),
currenths->FPR->prints[i]->line);
p = xml_convert(FPR->prints[i]->OS_name),
FPR->prints[i]->line);
free(p);
i++;
}
if (currenths->FPR->num_perfect_matches == 1)
if (FPR->num_perfect_matches == 1)
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,
"OS details: %s",
currenths->FPR->prints[0]->OS_name);
FPR->prints[0]->OS_name);
else {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,
"OS details: %s",
currenths->FPR->prints[0]->OS_name);
FPR->prints[0]->OS_name);
i = 1;
while(currenths->FPR->accuracy[i] == 1) {
while(FPR->accuracy[i] == 1) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,", %s",
currenths->FPR->prints[i]->OS_name);
FPR->prints[i]->OS_name);
i++;
}
}
} else {
if ((o.osscan_guess || !currenths->FPR->fingerprintSuitableForSubmission()) &&
currenths->FPR->num_matches > 0) {
if ((o.osscan_guess || !FPR->fingerprintSuitableForSubmission()) && FPR->num_matches > 0) {
/* Print the best guesses available */
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Aggressive OS guesses: %s (%d%%)", currenths->FPR->prints[0]->OS_name, (int) (currenths->FPR->accuracy[0] * 100));
for(i=1; i < 10 && currenths->FPR->num_matches > i &&
currenths->FPR->accuracy[i] >
currenths->FPR->accuracy[0] - 0.10; i++) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Aggressive OS guesses: %s (%d%%)", FPR->prints[0]->OS_name, (int) (FPR->accuracy[0] * 100));
for(i=1; i < 10 && FPR->num_matches > i && FPR->accuracy[i] > FPR->accuracy[0] - 0.10; i++) {
char *p;
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,", %s (%d%%)", currenths->FPR->prints[i]->OS_name, (int) (currenths->FPR->accuracy[i] * 100));
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,", %s (%d%%)", FPR->prints[i]->OS_name, (int) (FPR->accuracy[i] * 100));
log_write(LOG_XML, "<osmatch name=\"%s\" accuracy=\"%d\" line=\"%d\"/>\n",
p = xml_convert(currenths->FPR->prints[i]->OS_name),
(int) (currenths->FPR->accuracy[i] * 100),
currenths->FPR->prints[i]->line);
p = xml_convert(FPR->prints[i]->OS_name),
(int) (FPR->accuracy[i] * 100),
FPR->prints[i]->line);
free(p);
}
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, "\n");
}
if (currenths->FPR->fingerprintSuitableForSubmission()) {
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT,"No exact OS matches for host (If you know what OS is running on it, see http://www.insecure.org/cgi-bin/nmap-submit.cgi).\nTCP/IP fingerprint:\n%s\n", mergeFPs(currenths->FPR->FPs, currenths->FPR->numFPs, currenths->FPR->osscan_opentcpport, currenths->FPR->osscan_closedtcpport, currenths->MACAddress()));
if (FPR->fingerprintSuitableForSubmission()) {
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT,"No exact OS matches for host (If you know what OS is running on it, see http://www.insecure.org/cgi-bin/nmap-submit.cgi).\nTCP/IP fingerprint:\n%s\n",
mergeFPs(FPR->FPs, FPR->numFPs, true,
currenths->v4hostip(), distance, currenths->MACAddress(),
FPR->osscan_opentcpport, FPR->osscan_closedtcpport, FPR->osscan_closedudpport,
wrapFP));
} else {
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT,"No exact OS matches for host (test conditions non-ideal).");
if (o.verbose > 1)
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT, "\nTCP/IP fingerprint:\n%s", mergeFPs(currenths->FPR->FPs, currenths->FPR->numFPs, currenths->FPR->osscan_opentcpport, currenths->FPR->osscan_closedtcpport, currenths->MACAddress()));
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT, "\nTCP/IP fingerprint:\n%s",
mergeFPs(FPR->FPs, FPR->numFPs, false,
currenths->v4hostip(), distance, currenths->MACAddress(),
FPR->osscan_opentcpport, FPR->osscan_closedtcpport, FPR->osscan_closedudpport,
false));
}
}
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\n");
if (currenths->FPR->goodFP >= 0 && (o.debugging || o.verbose > 1) && currenths->FPR->num_perfect_matches > 0 ) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"OS Fingerprint:\n%s\n", fp2ascii(currenths->FPR->FPs[currenths->FPR->goodFP]));
if (FPR->goodFP >= 0 && (o.debugging || o.verbose > 1) && FPR->num_perfect_matches > 0 ) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"OS Fingerprint:\n%s\n", fp2ascii(FPR->FPs[FPR->goodFP]));
}
} else if (currenths->FPR->overall_results == OSSCAN_NOMATCHES) {
if (o.scan_delay < 500 && currenths->FPR->osscan_opentcpport > 0 &&
currenths->FPR->osscan_closedtcpport > 0 ) {
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT,"No OS matches for host (If you know what OS is running on it, see http://www.insecure.org/cgi-bin/nmap-submit.cgi).\nTCP/IP fingerprint:\n%s\n", mergeFPs(currenths->FPR->FPs, currenths->FPR->numFPs, currenths->FPR->osscan_opentcpport, currenths->FPR->osscan_closedtcpport, currenths->MACAddress()));
} else if (FPR->overall_results == OSSCAN_NOMATCHES) {
if (FPR->fingerprintSuitableForSubmission()) {
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT,"No OS matches for host (If you know what OS is running on it, see http://www.insecure.org/cgi-bin/nmap-submit.cgi).\nTCP/IP fingerprint:\n%s\n",
mergeFPs(FPR->FPs, FPR->numFPs, true,
currenths->v4hostip(), distance, currenths->MACAddress(),
FPR->osscan_opentcpport, FPR->osscan_closedtcpport, FPR->osscan_closedudpport,
wrapFP));
} else {
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT,"No OS matches for host (test conditions non-ideal).\nTCP/IP fingerprint:\n%s\n", mergeFPs(currenths->FPR->FPs, currenths->FPR->numFPs, currenths->FPR->osscan_opentcpport, currenths->FPR->osscan_closedtcpport, currenths->MACAddress()));
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT,"No OS matches for host (test conditions non-ideal).\n");
if (o.verbose > 1)
log_write(LOG_NORMAL|LOG_SKID_NOXLT|LOG_STDOUT, "\nTCP/IP fingerprint:\n%s",
mergeFPs(FPR->FPs, FPR->numFPs, false,
currenths->v4hostip(), distance, currenths->MACAddress(),
FPR->osscan_opentcpport, FPR->osscan_closedtcpport, FPR->osscan_closedudpport,
false));
}
} else if (currenths->FPR->overall_results == OSSCAN_TOOMANYMATCHES || (currenths->FPR->num_perfect_matches > 8 && !o.debugging))
{
} else if (FPR->overall_results == OSSCAN_TOOMANYMATCHES || (FPR->num_perfect_matches > 8 && !o.debugging)) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Too many fingerprints match this host to give specific OS details\n");
if (o.debugging || o.verbose) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"TCP/IP fingerprint:\n%s", mergeFPs(currenths->FPR->FPs, currenths->FPR->numFPs, currenths->FPR->osscan_opentcpport, currenths->FPR->osscan_closedtcpport, currenths->MACAddress()));
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"TCP/IP fingerprint:\n%s",
mergeFPs(FPR->FPs, FPR->numFPs, false,
currenths->v4hostip(), distance, currenths->MACAddress(),
FPR->osscan_opentcpport, FPR->osscan_closedtcpport, FPR->osscan_closedudpport,
false));
}
} else { assert(0); }
if (o.debugging || o.verbose) {
log_write(LOG_XML,"<osfingerprint fingerprint=\"\n%s\" />\n",
mergeFPs(currenths->FPR->FPs, currenths->FPR->numFPs,
currenths->FPR->osscan_opentcpport,
currenths->FPR->osscan_closedtcpport,
currenths->MACAddress()));
mergeFPs(FPR->FPs, FPR->numFPs, false,
currenths->v4hostip(), distance, currenths->MACAddress(),
FPR->osscan_opentcpport, FPR->osscan_closedtcpport, FPR->osscan_closedudpport,
false));
}
log_write(LOG_XML, "</os>\n");
if (currenths->seq.lastboot) {
@ -1330,10 +1394,15 @@ void printosscanoutput(Target *currenths) {
gettimeofday(&tv, NULL);
strncpy(tmbuf, ctime(&(currenths->seq.lastboot)), sizeof(tmbuf));
chomp(tmbuf);
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Uptime %.3f days (since %s)\n", (double) (tv.tv_sec - currenths->seq.lastboot) / 86400, tmbuf);
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Uptime: %.3f days (since %s)\n", (double) (tv.tv_sec - currenths->seq.lastboot) / 86400, tmbuf);
log_write(LOG_XML, "<uptime seconds=\"%li\" lastboot=\"%s\" />\n", tv.tv_sec - currenths->seq.lastboot, tmbuf);
}
if (distance!=-1) {
log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT, "Network Distance: %d hops\n", distance);
log_write(LOG_XML, "<distance value=\"%d\" />\n", distance);
}
if (currenths->seq.responses > 3) {
p=numlst;
for(i=0; i < currenths->seq.responses; i++) {
@ -1379,12 +1448,9 @@ void printosscanoutput(Target *currenths) {
}
log_write(LOG_XML, " />\n");
}
}
log_flush_all();
}
/* An auxillary function for printserviceinfooutput(). Returns
non-zero if a and b are considered the same hostnames. */
static int hostcmp(const char *a, const char *b) {

View file

@ -2136,9 +2136,9 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
}
for(decoy = 0; decoy < o.numdecoys; decoy++) {
packet = build_tcp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl,
ipid, sport, pspec->pd.tcp.dport, seq, ack,
pspec->pd.tcp.flags, 0, tcpops, tcpopslen,
packet = build_tcp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl, false,
ipid, sport, pspec->pd.tcp.dport, seq, ack, 0,
pspec->pd.tcp.flags, 0, 0, tcpops, tcpopslen,
o.extra_payload, o.extra_payload_length,
&packetlen);
if (decoy == o.decoyturn) {
@ -2166,15 +2166,15 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
switch(pspec->proto) {
case IPPROTO_TCP:
packet = build_tcp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl,
packet = build_tcp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl, false,
ipid, sport, o.magic_port, get_random_u32(),
get_random_u32(), TH_ACK, 0, NULL,
get_random_u32(), 0, TH_ACK, 0, 0, NULL,
0, o.extra_payload, o.extra_payload_length,
&packetlen);
break;
case IPPROTO_ICMP:
packet = build_icmp_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl,
ipid, 0, 0, 8, 0, o.extra_payload,
ipid, 0, false, 0, 0, 8, 0, o.extra_payload,
o.extra_payload_length, &packetlen);
break;
case IPPROTO_UDP:
@ -2186,7 +2186,7 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
break;
default:
packet = build_ip_raw(&o.decoys[decoy], hss->target->v4hostip(), o.ttl,
pspec->proto, ipid,
pspec->proto, ipid, 0, false,
o.extra_payload, o.extra_payload_length,
&packetlen);
break;

View file

@ -3,7 +3,7 @@ CC=gcc
CPP=g++
INCLUDE_FLAGS= -I.. -I../nbase -I../libpcap
LINK_FLAGS=-L.. -L../nbase -L../libpcap
NMAP_OBJS=../osscan.o ../nmap_error.o ../utils.o ../tcpip.o ../output.o ../nmap.o ../scan_engine.o ../portlist.o ../timing.o ../nmap_rpc.o ../charpool.o ../services.o ../targets.o ../idle_scan.o ../MACLookup.o ../protocols.o ../FingerPrintResults.o ../NmapOps.o ../TargetGroup.o ../Target.o ../NmapOutputTable.o ../service_scan.o ../nmap_tty.o ../nmap_dns.o ../nsock/src/libnsock.a
NMAP_OBJS=../osscan.o ../osscan2.o ../nmap_error.o ../utils.o ../tcpip.o ../output.o ../nmap.o ../scan_engine.o ../portlist.o ../timing.o ../nmap_rpc.o ../charpool.o ../services.o ../targets.o ../idle_scan.o ../MACLookup.o ../protocols.o ../FingerPrintResults.o ../NmapOps.o ../TargetGroup.o ../Target.o ../NmapOutputTable.o ../service_scan.o ../nmap_tty.o ../nmap_dns.o ../nsock/src/libnsock.a
DEFINES=-DHAVE_CONFIG_H=1
DATAFILES = nmap-os-fingerprints nmap-service-probes nmap-services nmap-rpc nmap-protocols nmap-mac-prefixes
SHTOOL = ../shtool

View file

@ -925,10 +925,10 @@ else {
o.decoys[o.decoyturn].s_addr = target->v4source().s_addr;
if (pingtype & PINGTYPE_TCP_USE_SYN) {
send_tcp_raw_decoys( rawsd, eth, target->v4hostip(), o.ttl, sportbase + trynum, probe_port, myseq, myack, TH_SYN, 0, (u8 *) "\x02\x04\x05\xb4", 4, o.extra_payload,
send_tcp_raw_decoys( rawsd, eth, target->v4hostip(), o.ttl, false, sportbase + trynum, probe_port, myseq, myack, 0, TH_SYN, 0, 0, (u8 *) "\x02\x04\x05\xb4", 4, o.extra_payload,
o.extra_payload_length);
} else {
send_tcp_raw_decoys( rawsd, eth, target->v4hostip(), o.ttl, sportbase + trynum, probe_port, myseq, myack, TH_ACK, 0, NULL, 0, o.extra_payload,
send_tcp_raw_decoys( rawsd, eth, target->v4hostip(), o.ttl, false, sportbase + trynum, probe_port, myseq, myack, 0, TH_ACK, 0, 0, NULL, 0, o.extra_payload,
o.extra_payload_length);
}

View file

@ -645,6 +645,31 @@ char dev[128];
return 0;
}
int isipprivate(const struct in_addr * const addr) {
char *ipc;
unsigned char i1, i2;
if(!addr) return 0;
ipc = (char *) &(addr->s_addr);
i1 = ipc[0];
i2 = ipc[1];
/* 10.0.0.0/8 */
if (i1 == 10)
return 1;
/* 172.16.0.0/12 */
if (i1 == 172 && i2 >= 16 && i2 <= 31)
return 1;
/* 192.168.0.0/16 */
if (i1 == 192 && i2 == 168)
return 1;
return 0;
}
#ifdef WIN32
/* Convert a dnet interface name into the long pcap style. This also caches the data
to speed things up. Fills out pcapdev (up to pcapdevlen) and returns true if it finds anything.
@ -830,16 +855,16 @@ void eth_close_cached() {
}
int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
const struct in_addr *victim, int ttl,
u16 sport, u16 dport, u32 seq, u32 ack, u8 flags,
u16 window, u8 *options, int optlen, char *data,
const struct in_addr *victim, int ttl, bool df,
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
u16 window, u16 urp, u8 *options, int optlen, char *data,
u16 datalen)
{
int decoy;
for(decoy = 0; decoy < o.numdecoys; decoy++)
if (send_tcp_raw(sd, eth, &o.decoys[decoy], victim, ttl, sport, dport,
seq, ack, flags, window, options, optlen, data,
if (send_tcp_raw(sd, eth, &o.decoys[decoy], victim, ttl, df, sport, dport,
seq, ack, reserved, flags, window, urp, options, optlen, data,
datalen) == -1)
return -1;
@ -853,9 +878,9 @@ int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
finished with the packet. The packet length is returned in
packetlen, which must be a valid int pointer. */
u8 *build_tcp_raw(const struct in_addr *source,
const struct in_addr *victim, int ttl,
u16 ipid, u16 sport, u16 dport, u32 seq, u32 ack, u8 flags,
u16 window, u8 *options, int optlen, char *data,
const struct in_addr *victim, int ttl, u16 ipid, bool df,
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
u16 window, u16 urp, u8 *options, int optlen, char *data,
u16 datalen, u32 *packetlen) {
struct pseudo_header {
@ -907,6 +932,8 @@ if (ack)
/*else if (flags & TH_ACK)
tcp->th_ack = rand() + rand();*/
if (reserved)
tcp->th_x2 = reserved & 0x0F;
tcp->th_off = 5 + (optlen /4) /*words*/;
tcp->th_flags = flags;
@ -914,6 +941,10 @@ if (window)
tcp->th_win = htons(window);
else tcp->th_win = htons(1024 * (myttl % 4 + 1)); /* Who cares */
/* Urgend pointer */
if (urp)
tcp->th_urp = htons(urp);
/* We should probably copy the data over too */
if (data && datalen)
memcpy(packet + sizeof(struct ip) + sizeof(struct tcphdr) + optlen, data, datalen);
@ -941,6 +972,7 @@ get_random_bytes(&(ip->ip_id), 2);
ip->ip_ttl = myttl;
ip->ip_p = IPPROTO_TCP;
ip->ip_id = ipid;
if(df) ip->ip_off |= htons(IP_DF);
ip->ip_src.s_addr = source->s_addr;
#ifdef WIN32
// I'm not sure why this is --Fyodor
@ -959,16 +991,16 @@ ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip));
/* You need to call sethdrinclude(sd) on the sending sd before calling this */
int send_tcp_raw( int sd, struct eth_nfo *eth, const struct in_addr *source,
const struct in_addr *victim, int ttl,
u16 sport, u16 dport, u32 seq, u32 ack, u8 flags,
u16 window, u8 *options, int optlen, char *data,
const struct in_addr *victim, int ttl, bool df,
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
u16 window, u16 urp, u8 *options, int optlen, char *data,
u16 datalen)
{
unsigned int packetlen;
int res = -1;
u8 *packet = build_tcp_raw(source, victim, ttl, get_random_u16(), sport,
dport, seq, ack, flags, window, options, optlen,
u8 *packet = build_tcp_raw(source, victim, ttl, get_random_u16(), df, sport,
dport, seq, ack, reserved, flags, window, urp, options, optlen,
data, datalen, &packetlen);
if (!packet) return -1;
res = send_ip_packet(sd, eth, packet, packetlen);
@ -1134,7 +1166,7 @@ int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet, unsigned int packetl
finished with the packet. The packet length is returned in
packetlen, which must be a valid int pointer. */
u8 *build_icmp_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u16 ipid, u16 seq, unsigned short id, u8 ptype,
int ttl, u16 ipid, u8 tos, bool df, u16 seq, unsigned short id, u8 ptype,
u8 pcode, char *data, u16 datalen, u32 *packetlen) {
struct ppkt {
@ -1153,7 +1185,7 @@ char *ping = (char *) &pingpkt;
pingpkt.type = ptype;
pingpkt.code = pcode;
if (ptype == 8 && pcode == 0) /* echo request */ {
if (ptype == 8) /* echo request */ {
icmplen = 8;
} else if (ptype == 13 && pcode == 0) /* ICMP timestamp req */ {
icmplen = 20;
@ -1173,7 +1205,6 @@ char *ping = (char *) &pingpkt;
}
/* Fill out the ping packet */
pingpkt.code = 0;
pingpkt.id = id;
pingpkt.seq = seq;
pingpkt.checksum = 0;
@ -1182,7 +1213,7 @@ pingpkt.checksum = in_cksum((unsigned short *)ping, icmplen);
if ( o.badsum )
--pingpkt.checksum;
return build_ip_raw(source, victim, o.ttl, IPPROTO_ICMP, get_random_u16(),
return build_ip_raw(source, victim, o.ttl, IPPROTO_ICMP, get_random_u16(), tos, df,
ping, icmplen, packetlen);
}
@ -1420,7 +1451,7 @@ int send_udp_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
finished with the packet. The packet length is returned in
packetlen, which must be a valid int pointer. */
u8 *build_ip_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u8 proto, u16 ipid, char *data, u16 datalen,
int ttl, u8 proto, u16 ipid, u8 tos, bool df, char *data, u16 datalen,
u32 *packetlen)
{
@ -1448,8 +1479,10 @@ memset((char *) packet, 0, sizeof(struct ip));
ip->ip_v = 4;
ip->ip_hl = 5;
ip->ip_tos = tos;
ip->ip_len = htons(sizeof(struct ip) + datalen);
ip->ip_id = htons(ipid);
if(df) ip->ip_off |= htons(IP_DF);
ip->ip_ttl = myttl;
ip->ip_p = proto;
ip->ip_src.s_addr = source->s_addr;
@ -1480,7 +1513,7 @@ int send_ip_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
int res = -1;
u8 *packet = build_ip_raw(source, victim, ttl, proto, get_random_u16(),
data, datalen, &packetlen);
IP_TOS_DEFAULT, false, data, datalen, &packetlen);
if (!packet) return -1;
res = send_ip_packet(sd, eth, packet, packetlen);

26
tcpip.h
View file

@ -570,9 +570,9 @@ unsigned short in_cksum(u16 *ptr,int nbytes);
/* Build and send a raw tcp packet. If TTL is -1, a partially random
(but likely large enough) one is chosen */
int send_tcp_raw( int sd, struct eth_nfo *eth, const struct in_addr *source,
const struct in_addr *victim, int ttl,
u16 sport, u16 dport, u32 seq, u32 ack, u8 flags,
u16 window, u8 *options, int optlen, char *data,
const struct in_addr *victim, int ttl, bool df,
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
u16 window, u16 urp, u8 *options, int optlen, char *data,
u16 datalen);
int send_udp_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
const struct in_addr *victim, int ttl, u16 sport,
@ -588,11 +588,10 @@ int send_ip_raw( int sd, struct eth_nfo *eth, struct in_addr *source,
actually sent by this function. Caller must delete the buffer when
finished with the packet. The packet length is returned in
packetlen, which must be a valid int pointer. */
u8 *build_tcp_raw(const struct in_addr *source,
const struct in_addr *victim, int ttl,
u16 ipid, u16 sport, u16 dport, u32 seq, u32 ack, u8 flags,
u16 window, u8 *options, int optlen, char *data,
u16 datalen, u32 *packetlen);
u8 *build_tcp_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u16 ipid, bool df, u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved,
u8 flags, u16 window, u16 urp, u8 *options, int optlen, char *data, u16 datalen,
u32 *packetlen);
/* Builds a UDP packet (including an IP header) by packing the fields
with the given information. It allocates a new buffer to store the
@ -611,7 +610,7 @@ u8 *build_udp_raw(struct in_addr *source, const struct in_addr *victim,
finished with the packet. The packet length is returned in
packetlen, which must be a valid int pointer. */
u8 *build_icmp_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u16 ipid, u16 seq, unsigned short id, u8 ptype,
int ttl, u16 ipid, u8 tos, bool df, u16 seq, unsigned short id, u8 ptype,
u8 pcode, char *data, u16 datalen, u32 *packetlen);
/* Builds an IP packet (including an IP header) by packing the fields
@ -621,7 +620,7 @@ u8 *build_icmp_raw(const struct in_addr *source, const struct in_addr *victim,
finished with the packet. The packet length is returned in
packetlen, which must be a valid int pointer. */
u8 *build_ip_raw(const struct in_addr *source, const struct in_addr *victim,
int ttl, u8 proto, u16 ipid, char *data, u16 datalen,
int ttl, u8 proto, u16 ipid, u8 tos, bool df, char *data, u16 datalen,
u32 *packetlen);
/* Send a pre-built IPv4 packet */
@ -630,9 +629,9 @@ int send_ip_packet(int sd, struct eth_nfo *eth, u8 *packet,
/* Decoy versions of the raw packet sending functions ... */
int send_tcp_raw_decoys( int sd, struct eth_nfo *eth,
const struct in_addr *victim, int ttl,
u16 sport, u16 dport, u32 seq, u32 ack, u8 flags,
u16 window, u8 *options, int optlen, char *data,
const struct in_addr *victim, int ttl, bool df,
u16 sport, u16 dport, u32 seq, u32 ack, u8 reserved, u8 flags,
u16 window, u16 urp, u8 *options, int optlen, char *data,
u16 datalen);
int send_udp_raw_decoys( int sd, struct eth_nfo *eth,
@ -723,6 +722,7 @@ int setTargetMACIfAvailable(Target *target, struct link_header *linkhdr,
bool setTargetNextHopMAC(Target *target);
int islocalhost(const struct in_addr * const addr);
int isipprivate(const struct in_addr * const addr);
int unblock_socket(int sd);
// Takes a protocol number like IPPROTO_TCP, IPPROTO_UDP, or