mirror of
https://github.com/nmap/nmap.git
synced 2026-02-07 05:56:34 +00:00
misc changes, but crashing. ... about to figure out why
This commit is contained in:
@@ -20,6 +20,11 @@ o Added "Exclude" directive to nmap-service-probes grammar which
|
||||
probes, etc. If you really want to scan all ports, specify
|
||||
--allports. This patch came from Doug Hoyte (doug(a)hcsw.org).
|
||||
|
||||
o Chagned the interesting ports array from a 65K-member array of
|
||||
pointers into an STL list. This noticeable reduces memory usage in
|
||||
some cases, and should also give a slight runtime performance
|
||||
boost. This patch was written by Paul Tarjan (ptarjan(a)gmail.com).
|
||||
|
||||
o Integrated a bunch of nmap-service-probes fingerprints from Doug
|
||||
Hoyte (doug(a)hcsw.org)
|
||||
|
||||
|
||||
@@ -5912,7 +5912,7 @@ T7(DF=N%W=0%ACK=S%Flags=AR%Ops=)
|
||||
PU(DF=N%TOS=C0%IPLEN=38%RIPTL=134%RID=E%RIPCK=F%UCK=0%ULEN=134%DAT=E)
|
||||
|
||||
Fingerprint F5 Labs Big/IP HA TCP/IP Load Balancer (BSDI kernel/x86)
|
||||
Class F5 Labs | BSDI || load balancer
|
||||
Class F5 Labs | BSD/OS || load balancer
|
||||
TSeq(Class=RI%gcd=<8%SI=<75C74&>12C4)
|
||||
T1(DF=Y%W=402E%ACK=S++%Flags=AS%Ops=MNWNNT)
|
||||
T2(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
|
||||
@@ -10793,7 +10793,7 @@ PU(Resp=N)
|
||||
|
||||
# Microsoft Windows Longhorn Preview, Version 6.0 Build 4051.idx 02.031001-1340
|
||||
Fingerprint Microsoft Windows Longhorn Preview
|
||||
Class Microsoft | Windows Longhorn || general purpose
|
||||
Class Microsoft | Windows | Windows Longhorn | general purpose
|
||||
TSeq(Class=TR%gcd=<6%IPID=I%TS=100HZ)
|
||||
T1(DF=Y%W=0%ACK=S++%Flags=AR%Ops=)
|
||||
T2(Resp=N)
|
||||
|
||||
2388
nmap-service-probes
2388
nmap-service-probes
File diff suppressed because it is too large
Load Diff
15
output.cc
15
output.cc
@@ -235,7 +235,7 @@ void printportoutput(Target *currenths, PortList *plist) {
|
||||
Port *current;
|
||||
int numignoredports;
|
||||
int portno, protocount;
|
||||
Port **protoarrays[2];
|
||||
map<u16, Port*> protoarrays[2];
|
||||
char hostname[1200];
|
||||
int istate = plist->getIgnoredPortState();
|
||||
numignoredports = plist->state_counts[istate];
|
||||
@@ -251,6 +251,7 @@ void printportoutput(Target *currenths, PortList *plist) {
|
||||
int numrows;
|
||||
vector<const char *> saved_servicefps;
|
||||
|
||||
//cout << numignoredports << " " << plist->numports << endl;
|
||||
assert(numignoredports <= plist->numports);
|
||||
|
||||
|
||||
@@ -323,8 +324,8 @@ void printportoutput(Target *currenths, PortList *plist) {
|
||||
rowno = 1;
|
||||
if (o.ipprotscan) {
|
||||
for (portno = 0; portno < 256; portno++) {
|
||||
if (!plist->ip_prots[portno]) continue;
|
||||
current = plist->ip_prots[portno];
|
||||
if (!plist->ip_ports[portno]) continue;
|
||||
current = plist->ip_ports[portno];
|
||||
if (current->state != istate) {
|
||||
if (!first) log_write(LOG_MACHINE,", ");
|
||||
else first = 0;
|
||||
@@ -345,12 +346,10 @@ void printportoutput(Target *currenths, PortList *plist) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(portno = 0; portno < 65536; portno++) {
|
||||
for(protocount = 0; protocount < 2; protocount++) {
|
||||
if (protoarrays[protocount] && protoarrays[protocount][portno])
|
||||
current = protoarrays[protocount][portno];
|
||||
else continue;
|
||||
|
||||
for(map<u16,Port*>::iterator iter = protoarrays[protocount].begin(); iter != protoarrays[protocount].end(); iter++) {
|
||||
current = (*iter).second;
|
||||
|
||||
if (current->state != istate) {
|
||||
if (!first) log_write(LOG_MACHINE,", ");
|
||||
else first = 0;
|
||||
|
||||
208
portlist.cc
208
portlist.cc
@@ -121,6 +121,7 @@ Port::Port() {
|
||||
serviceprobe_results = PROBESTATE_INITIAL;
|
||||
serviceprobe_service = NULL;
|
||||
serviceprobe_product = serviceprobe_version = serviceprobe_extrainfo = NULL;
|
||||
serviceprobe_hostname = serviceprobe_ostype = serviceprobe_devicetype = NULL;
|
||||
serviceprobe_tunnel = SERVICE_TUNNEL_NONE;
|
||||
serviceprobe_fp = NULL;
|
||||
}
|
||||
@@ -134,6 +135,12 @@ Port::~Port() {
|
||||
free(serviceprobe_version);
|
||||
if (serviceprobe_extrainfo)
|
||||
free(serviceprobe_extrainfo);
|
||||
if (serviceprobe_hostname)
|
||||
free(serviceprobe_hostname);
|
||||
if (serviceprobe_ostype)
|
||||
free(serviceprobe_ostype);
|
||||
if (serviceprobe_devicetype)
|
||||
free(serviceprobe_devicetype);
|
||||
if (serviceprobe_service)
|
||||
free(serviceprobe_service);
|
||||
if (serviceprobe_fp)
|
||||
@@ -144,38 +151,46 @@ Port::~Port() {
|
||||
// out sd->fullversion. If unavailable, it will be set to zero length.
|
||||
static void populateFullVersionString(struct serviceDeductions *sd) {
|
||||
char *dst = sd->fullversion;
|
||||
char *end = sd->fullversion + sizeof(sd->fullversion);
|
||||
int len;
|
||||
unsigned int spaceleft = sizeof(sd->fullversion) - 1;
|
||||
|
||||
if (sd->product) {
|
||||
len = strlen(sd->product);
|
||||
len = MIN((int) sizeof(sd->fullversion) - 1, len);
|
||||
memcpy(dst, sd->product, len);
|
||||
dst += len;
|
||||
dst[0] = '\0';
|
||||
|
||||
if (sd->product && spaceleft >= strlen(sd->product)) {
|
||||
strncat(dst, sd->product, spaceleft);
|
||||
spaceleft -= strlen(sd->product);
|
||||
}
|
||||
|
||||
if (sd->version && dst < end - 1) {
|
||||
if (dst != sd->fullversion)
|
||||
*(dst++) = ' ';
|
||||
len = strlen(sd->version);
|
||||
len = MIN(len, end - dst - 1);
|
||||
memcpy(dst, sd->version, len);
|
||||
dst += len;
|
||||
if (sd->version && spaceleft >= (strlen(sd->version) + 1)) {
|
||||
strncat(dst, " ", spaceleft);
|
||||
strncat(dst, sd->version, spaceleft);
|
||||
spaceleft -= strlen(sd->version) + 1;
|
||||
}
|
||||
|
||||
if (sd->extrainfo && dst < end) {
|
||||
len = strlen(sd->extrainfo);
|
||||
if (len < end - dst - 4) { // 4 == " ()\0"
|
||||
if (dst != sd->fullversion)
|
||||
*(dst++) = ' ';
|
||||
*(dst++) = '(';
|
||||
memcpy(dst, sd->extrainfo, len);
|
||||
dst += len;
|
||||
*(dst++) = ')';
|
||||
if (sd->extrainfo && spaceleft >= (strlen(sd->extrainfo) + 3)) {
|
||||
strncat(dst, " (", spaceleft);
|
||||
strncat(dst, sd->extrainfo, spaceleft);
|
||||
strncat(dst, ")", spaceleft);
|
||||
spaceleft -= strlen(sd->extrainfo) + 3;
|
||||
}
|
||||
|
||||
if (sd->hostname && spaceleft >= (strlen(sd->hostname) + 7)) {
|
||||
strncat(dst, " Host: ", spaceleft);
|
||||
strncat(dst, sd->hostname, spaceleft);
|
||||
spaceleft -= strlen(sd->hostname) + 7;
|
||||
}
|
||||
|
||||
if (sd->ostype && spaceleft >= (strlen(sd->ostype) + 5)) {
|
||||
strncat(dst, " OS: ", spaceleft);
|
||||
strncat(dst, sd->ostype, spaceleft);
|
||||
spaceleft -= strlen(sd->ostype) + 5;
|
||||
}
|
||||
|
||||
if (sd->devicetype && spaceleft >= (strlen(sd->devicetype) + 9)) {
|
||||
strncat(dst, " Device: ", spaceleft);
|
||||
strncat(dst, sd->devicetype, spaceleft);
|
||||
spaceleft -= strlen(sd->devicetype) + 9;
|
||||
}
|
||||
|
||||
*(dst++) = '\0'; // Will always have space
|
||||
}
|
||||
|
||||
|
||||
@@ -203,6 +218,9 @@ int Port::getServiceDeductions(struct serviceDeductions *sd) {
|
||||
sd->dtype = SERVICE_DETECTION_PROBED; // RPC counts as probed
|
||||
sd->version = serviceprobe_version;
|
||||
sd->extrainfo = serviceprobe_extrainfo;
|
||||
sd->hostname = serviceprobe_hostname;
|
||||
sd->ostype = serviceprobe_ostype;
|
||||
sd->devicetype = serviceprobe_devicetype;
|
||||
populateFullVersionString(sd);
|
||||
return 0;
|
||||
} else if (serviceprobe_results == PROBESTATE_FINISHED_HARDMATCHED
|
||||
@@ -214,6 +232,9 @@ int Port::getServiceDeductions(struct serviceDeductions *sd) {
|
||||
sd->product = serviceprobe_product;
|
||||
sd->version = serviceprobe_version;
|
||||
sd->extrainfo = serviceprobe_extrainfo;
|
||||
sd->hostname = serviceprobe_hostname;
|
||||
sd->ostype = serviceprobe_ostype;
|
||||
sd->devicetype = serviceprobe_devicetype;
|
||||
populateFullVersionString(sd);
|
||||
return 0;
|
||||
} else if (serviceprobe_results == PROBESTATE_EXCLUDED) {
|
||||
@@ -263,7 +284,8 @@ void Port::setServiceProbeResults(enum serviceprobestate sres,
|
||||
const char *sname,
|
||||
enum service_tunnel_type tunnel,
|
||||
const char *product, const char *version,
|
||||
const char *extrainfo,
|
||||
const char *extrainfo, const char *hostname,
|
||||
const char *ostype, const char *devicetype,
|
||||
const char *fingerprint) {
|
||||
|
||||
int slen;
|
||||
@@ -312,6 +334,45 @@ void Port::setServiceProbeResults(enum serviceprobestate sres,
|
||||
}
|
||||
}
|
||||
|
||||
if (hostname) {
|
||||
slen = strlen(hostname);
|
||||
if (slen > 128) slen = 128;
|
||||
serviceprobe_hostname = (char *) safe_malloc(slen + 1);
|
||||
memcpy(serviceprobe_hostname, hostname, slen);
|
||||
serviceprobe_hostname[slen] = '\0';
|
||||
p = (unsigned char *) serviceprobe_hostname;
|
||||
while(*p) {
|
||||
if (!isprint((int)*p)) *p = '.';
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ostype) {
|
||||
slen = strlen(ostype);
|
||||
if (slen > 64) slen = 64;
|
||||
serviceprobe_ostype = (char *) safe_malloc(slen + 1);
|
||||
memcpy(serviceprobe_ostype, ostype, slen);
|
||||
serviceprobe_ostype[slen] = '\0';
|
||||
p = (unsigned char *) serviceprobe_ostype;
|
||||
while(*p) {
|
||||
if (!isprint((int)*p)) *p = '.';
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (devicetype) {
|
||||
slen = strlen(devicetype);
|
||||
if (slen > 64) slen = 64;
|
||||
serviceprobe_devicetype = (char *) safe_malloc(slen + 1);
|
||||
memcpy(serviceprobe_devicetype, devicetype, slen);
|
||||
serviceprobe_devicetype[slen] = '\0';
|
||||
p = (unsigned char *) serviceprobe_devicetype;
|
||||
while(*p) {
|
||||
if (!isprint((int)*p)) *p = '.';
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets the results of an RPC scan. if rpc_status is not
|
||||
@@ -352,7 +413,6 @@ void Port::setRPCProbeResults(int rpcs, unsigned long rpcp,
|
||||
}
|
||||
|
||||
PortList::PortList() {
|
||||
udp_ports = tcp_ports = ip_prots = NULL;
|
||||
memset(state_counts, 0, sizeof(state_counts));
|
||||
memset(state_counts_udp, 0, sizeof(state_counts_udp));
|
||||
memset(state_counts_tcp, 0, sizeof(state_counts_tcp));
|
||||
@@ -362,34 +422,22 @@ PortList::PortList() {
|
||||
}
|
||||
|
||||
PortList::~PortList() {
|
||||
int i;
|
||||
|
||||
if (tcp_ports) {
|
||||
for(i=0; i < 65536; i++) {
|
||||
if (tcp_ports[i])
|
||||
delete tcp_ports[i];
|
||||
}
|
||||
free(tcp_ports);
|
||||
tcp_ports = NULL;
|
||||
}
|
||||
for(map<u16,Port*>::iterator iter = tcp_ports.begin(); iter != tcp_ports.end(); iter++)
|
||||
{
|
||||
delete (*iter).second;
|
||||
}
|
||||
|
||||
|
||||
if (udp_ports) {
|
||||
for(i=0; i < 65536; i++) {
|
||||
if (udp_ports[i])
|
||||
delete udp_ports[i];
|
||||
}
|
||||
free(udp_ports);
|
||||
udp_ports = NULL;
|
||||
}
|
||||
for(map<u16,Port*>::iterator iter = udp_ports.begin(); iter != udp_ports.end(); iter++)
|
||||
{
|
||||
delete (*iter).second;
|
||||
}
|
||||
|
||||
if (ip_prots) {
|
||||
for(i=0; i < 256; ++i) {
|
||||
if (ip_prots[i])
|
||||
delete ip_prots[i];
|
||||
}
|
||||
free(ip_prots);
|
||||
ip_prots = NULL;
|
||||
}
|
||||
for(map<u16,Port*>::iterator iter = ip_ports.begin(); iter != ip_ports.end(); iter++)
|
||||
{
|
||||
delete (*iter).second;
|
||||
}
|
||||
|
||||
if (idstr) {
|
||||
free(idstr);
|
||||
@@ -401,7 +449,7 @@ PortList::~PortList() {
|
||||
|
||||
int PortList::addPort(u16 portno, u8 protocol, char *owner, int state) {
|
||||
Port *current = NULL;
|
||||
Port **portarray = NULL;
|
||||
map < u16, Port* > *portarray = NULL; // This has to be a pointer so that we change the original and not a copy
|
||||
char msg[128];
|
||||
|
||||
assert(state < PORT_HIGHEST_STATE);
|
||||
@@ -425,27 +473,18 @@ int PortList::addPort(u16 portno, u8 protocol, char *owner, int state) {
|
||||
fatal("addPort: attempt to add port number %d with illegal state %d\n", portno, state);
|
||||
|
||||
if (protocol == IPPROTO_TCP) {
|
||||
if (!tcp_ports) {
|
||||
tcp_ports = (Port **) safe_zalloc(65536 * sizeof(Port *));
|
||||
}
|
||||
portarray = tcp_ports;
|
||||
portarray = &tcp_ports;
|
||||
} else if (protocol == IPPROTO_UDP) {
|
||||
if (!udp_ports) {
|
||||
udp_ports = (Port **) safe_zalloc(65536 * sizeof(Port *));
|
||||
}
|
||||
portarray = udp_ports;
|
||||
portarray = &udp_ports;
|
||||
} else if (protocol == IPPROTO_IP) {
|
||||
assert(portno < 256);
|
||||
if (!ip_prots) {
|
||||
ip_prots = (Port **) safe_zalloc(256 * sizeof(Port *));
|
||||
}
|
||||
portarray = ip_prots;
|
||||
portarray = &ip_ports;
|
||||
} else fatal("addPort: attempted port insertion with invalid protocol");
|
||||
|
||||
if (portarray[portno]) {
|
||||
if ((*portarray)[portno]) {
|
||||
/* We must discount our statistics from the old values. Also warn
|
||||
if a complete duplicate */
|
||||
current = portarray[portno];
|
||||
current = (*portarray)[portno];
|
||||
if (o.debugging && current->state == state && (!owner || !*owner)) {
|
||||
error("Duplicate port (%hu/%s)\n", portno, proto2ascii(protocol));
|
||||
}
|
||||
@@ -457,8 +496,8 @@ int PortList::addPort(u16 portno, u8 protocol, char *owner, int state) {
|
||||
} else
|
||||
state_counts_ip[current->state]--;
|
||||
} else {
|
||||
portarray[portno] = new Port();
|
||||
current = portarray[portno];
|
||||
(*portarray)[portno] = new Port();
|
||||
current = (*portarray)[portno];
|
||||
numports++;
|
||||
current->portno = portno;
|
||||
}
|
||||
@@ -479,22 +518,31 @@ int PortList::addPort(u16 portno, u8 protocol, char *owner, int state) {
|
||||
current->owner = strdup(owner);
|
||||
}
|
||||
|
||||
/* printf("\nCurrent Port List\n");
|
||||
for(map<u16,Port*>::iterator iter = (*portarray).begin(); iter != (*portarray).end(); iter++)
|
||||
printf("%d %d\n", (*iter).first, (*iter).second);
|
||||
*/
|
||||
|
||||
|
||||
return 0; /*success */
|
||||
}
|
||||
|
||||
int PortList::removePort(u16 portno, u8 protocol) {
|
||||
Port *answer = NULL;
|
||||
|
||||
if (protocol == IPPROTO_TCP && tcp_ports) {
|
||||
printf("Removed %d\n", portno);
|
||||
|
||||
if (protocol == IPPROTO_TCP) {
|
||||
answer = tcp_ports[portno];
|
||||
tcp_ports[portno] = NULL;
|
||||
tcp_ports.erase(portno);
|
||||
}
|
||||
|
||||
if (protocol == IPPROTO_UDP && udp_ports) {
|
||||
if (protocol == IPPROTO_UDP) {
|
||||
answer = udp_ports[portno];
|
||||
udp_ports[portno] = NULL;
|
||||
} else if (protocol == IPPROTO_IP && ip_prots) {
|
||||
answer = ip_prots[portno] = NULL;
|
||||
udp_ports.erase(portno);
|
||||
} else if (protocol == IPPROTO_IP) {
|
||||
answer = ip_ports[portno];
|
||||
ip_ports.erase(portno);
|
||||
}
|
||||
|
||||
if (!answer)
|
||||
@@ -527,14 +575,14 @@ void PortList::setIdStr(const char *id) {
|
||||
|
||||
Port *PortList::lookupPort(u16 portno, u8 protocol) {
|
||||
|
||||
if (protocol == IPPROTO_TCP && tcp_ports)
|
||||
if (protocol == IPPROTO_TCP)
|
||||
return tcp_ports[portno];
|
||||
|
||||
if (protocol == IPPROTO_UDP && udp_ports)
|
||||
if (protocol == IPPROTO_UDP)
|
||||
return udp_ports[portno];
|
||||
|
||||
if (protocol == IPPROTO_IP && ip_prots)
|
||||
return ip_prots[portno];
|
||||
if (protocol == IPPROTO_IP)
|
||||
return ip_ports[portno];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -588,7 +636,7 @@ if (afterthisport) {
|
||||
/* First we look for TCP ports ... */
|
||||
if (current_proto == IPPROTO_TCP) {
|
||||
if ((allowed_protocol == 0 || allowed_protocol == IPPROTO_TCP) &&
|
||||
current_proto == IPPROTO_TCP && tcp_ports)
|
||||
current_proto == IPPROTO_TCP)
|
||||
for(; current_portno < 65536; current_portno++) {
|
||||
if (tcp_ports[current_portno] &&
|
||||
(!allowed_state || tcp_ports[current_portno]->state == allowed_state))
|
||||
@@ -601,7 +649,7 @@ if (current_proto == IPPROTO_TCP) {
|
||||
}
|
||||
|
||||
if ((allowed_protocol == 0 || allowed_protocol == IPPROTO_UDP) &&
|
||||
current_proto == IPPROTO_UDP && udp_ports) {
|
||||
current_proto == IPPROTO_UDP) {
|
||||
for(; current_portno < 65536; current_portno++) {
|
||||
if (udp_ports[current_portno] &&
|
||||
(!allowed_state || udp_ports[current_portno]->state == allowed_state))
|
||||
|
||||
21
portlist.h
21
portlist.h
@@ -103,6 +103,9 @@
|
||||
#define PORTLIST_H
|
||||
|
||||
#include <nbase.h>
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
|
||||
/* port states */
|
||||
#define PORT_UNKNOWN 0
|
||||
@@ -150,10 +153,13 @@ struct serviceDeductions {
|
||||
// confident) expressing how accurate the service detection is
|
||||
// likely to be.
|
||||
int name_confidence;
|
||||
// Any of these three will be NULL if undetermined.
|
||||
// Any of these 6 can be NULL if we weren't able to determine it
|
||||
const char *product;
|
||||
const char *version;
|
||||
const char *extrainfo;
|
||||
const char *hostname;
|
||||
const char *ostype;
|
||||
const char *devicetype;
|
||||
// SERVICE_TUNNEL_NONE or SERVICE_TUNNEL_SSL
|
||||
enum service_tunnel_type service_tunnel;
|
||||
// This is the combined version of the three fields above. It will be
|
||||
@@ -198,7 +204,8 @@ class Port {
|
||||
// detected and we tried to tunnel through it ).
|
||||
void setServiceProbeResults(enum serviceprobestate sres, const char *sname,
|
||||
enum service_tunnel_type tunnel, const char *product,
|
||||
const char *version,
|
||||
const char *version, const char *hostname,
|
||||
const char *ostype, const char *devicetype,
|
||||
const char *extrainfo, const char *fingerprint);
|
||||
|
||||
/* Sets the results of an RPC scan. if rpc_status is not
|
||||
@@ -233,6 +240,9 @@ class Port {
|
||||
char *serviceprobe_product;
|
||||
char *serviceprobe_version;
|
||||
char *serviceprobe_extrainfo;
|
||||
char *serviceprobe_hostname;
|
||||
char *serviceprobe_ostype;
|
||||
char *serviceprobe_devicetype;
|
||||
enum service_tunnel_type serviceprobe_tunnel;
|
||||
// A fingerprint that the user can submit if the service wasn't recognized
|
||||
char *serviceprobe_fp;
|
||||
@@ -267,9 +277,10 @@ class PortList {
|
||||
bool allow_portzero);
|
||||
|
||||
Port *lookupPort(u16 portno, u8 protocol);
|
||||
Port **udp_ports;
|
||||
Port **tcp_ports;
|
||||
Port **ip_prots;
|
||||
map < u16, Port* > udp_ports;
|
||||
map < u16, Port* > tcp_ports;
|
||||
map < u16, Port* > ip_ports;
|
||||
|
||||
int state_counts[PORT_HIGHEST_STATE]; /* How many ports in list are in each
|
||||
state */
|
||||
int state_counts_udp[PORT_HIGHEST_STATE];
|
||||
|
||||
@@ -204,9 +204,16 @@ int doMatch(AllProbes *AP, char *fprint, int fplen, char *ipaddystr) {
|
||||
} else Strncpy(softmatch, MD->serviceName, sizeof(softmatch));
|
||||
} else {
|
||||
// YEAH! Found a hard match!
|
||||
if (MD->product || MD->version || MD->info)
|
||||
printf("MATCHED %ssvc %s |%s|%s|%s|%s: %s\n", nullprobecheat? "(NULLPROBE CHEAT) " : "", MD->serviceName, MD->product? MD->product : "", MD->version? MD->version : "", MD->info? MD->info : "", ipaddystr, fprint);
|
||||
else
|
||||
if (MD->product || MD->version || MD->info || MD->hostname || MD->ostype || MD->devicetype) {
|
||||
printf("MATCHED %ssvc %s", nullprobecheat? "(NULLPROBE CHEAT) " : "", MD->serviceName);
|
||||
if (MD->product) printf(" p|%s|", MD->product);
|
||||
if (MD->version) printf(" v|%s|", MD->version);
|
||||
if (MD->info) printf(" i|%s|", MD->info);
|
||||
if (MD->hostname) printf(" h|%s|", MD->hostname);
|
||||
if (MD->ostype) printf(" o|%s|", MD->ostype);
|
||||
if (MD->devicetype) printf(" d|%s|", MD->devicetype);
|
||||
printf(" %s: %s\n", ipaddystr, fprint);
|
||||
} else
|
||||
printf("MATCHED %ssvc %s (NO VERSION)%s: %s\n", nullprobecheat? "(NULLPROBE CHEAT) " : "", MD->serviceName, ipaddystr, fprint);
|
||||
return 0;
|
||||
}
|
||||
|
||||
160
service_scan.cc
160
service_scan.cc
@@ -155,11 +155,14 @@ public:
|
||||
Port *port; // The Port that this service represents (this copy is taken from inside Target)
|
||||
// if a match is found, it is placed here. Otherwise NULL
|
||||
const char *probe_matched;
|
||||
// If a match is found, any product/version/info is placed in these
|
||||
// 3 strings. Otherwise the string will be 0 length.
|
||||
// If a match is found, any product/version/info/hostname/ostype/devicetype
|
||||
// is placed in these 6 strings. Otherwise the string will be 0 length.
|
||||
char product_matched[80];
|
||||
char version_matched[80];
|
||||
char extrainfo_matched[128];
|
||||
char hostname_matched[128];
|
||||
char ostype_matched[64];
|
||||
char devicetype_matched[64];
|
||||
enum service_tunnel_type tunnel; /* SERVICE_TUNNEL_NONE, SERVICE_TUNNEL_SSL */
|
||||
// This stores our SSL session id, which will help speed up subsequent
|
||||
// SSL connections. It's overwritten each time. void* is used so we don't
|
||||
@@ -256,6 +259,7 @@ ServiceProbeMatch::ServiceProbeMatch() {
|
||||
servicename = NULL;
|
||||
matchstr = NULL;
|
||||
product_template = version_template = info_template = NULL;
|
||||
hostname_template = ostype_template = devicetype_template = NULL;
|
||||
regex_compiled = NULL;
|
||||
regex_extra = NULL;
|
||||
isInitialized = false;
|
||||
@@ -271,6 +275,9 @@ ServiceProbeMatch::~ServiceProbeMatch() {
|
||||
if (product_template) free(product_template);
|
||||
if (version_template) free(version_template);
|
||||
if (info_template) free(info_template);
|
||||
if (hostname_template) free(hostname_template);
|
||||
if (ostype_template) free(ostype_template);
|
||||
if (devicetype_template) free(devicetype_template);
|
||||
matchstrlen = 0;
|
||||
if (regex_compiled) pcre_free(regex_compiled);
|
||||
if (regex_extra) pcre_free(regex_extra);
|
||||
@@ -286,7 +293,8 @@ ServiceProbeMatch::~ServiceProbeMatch() {
|
||||
// function will abort the program if there is a syntax problem.
|
||||
void ServiceProbeMatch::InitMatch(const char *matchtext, int lineno) {
|
||||
const char *p;
|
||||
char delimchar;
|
||||
char *tmptemplate;
|
||||
char delimchar, modechar;
|
||||
int pcre_compile_ops = 0;
|
||||
const char *pcre_errptr = NULL;
|
||||
int pcre_erroffset = 0;
|
||||
@@ -375,56 +383,43 @@ void ServiceProbeMatch::InitMatch(const char *matchtext, int lineno) {
|
||||
fatal("ServiceProbeMatch::InitMatch: parse error on line %d of nmap-service-probes: match string must begin with 'm'", lineno);
|
||||
}
|
||||
|
||||
/* OK! Now we look for the optional version-detection
|
||||
product/version info in the form v/productname/version/info/
|
||||
(where '/' delimiter can be anything) */
|
||||
/* OK! Now we look for any templates of the form ?/.../
|
||||
* where ? is either p, v, i, h, o, or d. / is any
|
||||
* delimiter character and ... is a template */
|
||||
|
||||
while(1) {
|
||||
while(isspace(*matchtext)) matchtext++;
|
||||
if (isalnum(*matchtext)) {
|
||||
if (*matchtext == '\0' || *matchtext == '\r' || *matchtext == '\n') break;
|
||||
|
||||
if (isSoft)
|
||||
fatal("ServiceProbeMatch::InitMatch: illegal trailing garbage on line %d of nmap-service-probes - note that softmatch lines cannot have a version specifier.", lineno);
|
||||
if (*matchtext != 'v')
|
||||
fatal("ServiceProbeMatch::InitMatch: illegal trailing garbage (should be a version pattern match?) on line %d of nmap-service-probes", lineno);
|
||||
delimchar = *(++matchtext);
|
||||
++matchtext;
|
||||
// find the end of the productname
|
||||
|
||||
modechar = *(matchtext++);
|
||||
if (*matchtext == 0 || *matchtext == '\r' || *matchtext == '\n')
|
||||
fatal("ServiceProbeMatch::InitMatch: parse error on line %d of nmap-service-probes", lineno);
|
||||
|
||||
delimchar = *(matchtext++);
|
||||
|
||||
p = strchr(matchtext, delimchar);
|
||||
if (!p) fatal("ServiceProbeMatch::InitMatch: parse error on line %d of nmap-service-probes (in the version pattern - productname section)", lineno);
|
||||
if (!p) fatal("ServiceProbeMatch::InitMatch: parse error on line %d of nmap-service-probes", lineno);
|
||||
|
||||
tmptemplate = NULL;
|
||||
tmpbuflen = p - matchtext;
|
||||
if (tmpbuflen > 0) {
|
||||
product_template = (char *) safe_malloc(tmpbuflen + 1);
|
||||
memcpy(product_template, matchtext, tmpbuflen);
|
||||
product_template[tmpbuflen] = '\0';
|
||||
}
|
||||
// Now lets go after the version info
|
||||
matchtext = p+1;
|
||||
p = strchr(matchtext, delimchar);
|
||||
if (!p) fatal("ServiceProbeMatch::InitMatch: parse error on line %d of nmap-service-probes (in the version pattern - version section)", lineno);
|
||||
tmpbuflen = p - matchtext;
|
||||
if (tmpbuflen > 0) {
|
||||
version_template = (char *) safe_malloc(tmpbuflen + 1);
|
||||
memcpy(version_template, matchtext, tmpbuflen);
|
||||
version_template[tmpbuflen] = '\0';
|
||||
}
|
||||
// And finally for the "info"
|
||||
matchtext = p+1;
|
||||
p = strchr(matchtext, delimchar);
|
||||
if (!p) fatal("ServiceProbeMatch::InitMatch: parse error on line %d of nmap-service-probes (in the version pattern - info section)", lineno);
|
||||
tmpbuflen = p - matchtext;
|
||||
if (tmpbuflen > 0) {
|
||||
info_template = (char *) safe_malloc(tmpbuflen + 1);
|
||||
memcpy(info_template, matchtext, tmpbuflen);
|
||||
info_template[tmpbuflen] = '\0';
|
||||
tmptemplate = (char *) safe_malloc(tmpbuflen + 1);
|
||||
memcpy(tmptemplate, matchtext, tmpbuflen);
|
||||
tmptemplate[tmpbuflen] = '\0';
|
||||
}
|
||||
|
||||
// Insure there is no trailing junk after the version string
|
||||
// (usually cased by delimchar accidently being in the
|
||||
// product/version/info string).
|
||||
p++;
|
||||
while(*p && *p != '\r' && *p != '\n') {
|
||||
if (!isspace((int) *(unsigned char *)p)) fatal("ServiceProbeMatch::InitMatch: illegal trailing garbage (accidental version delimeter in your v//// string?) on line %d of nmap-service-probes", lineno);
|
||||
p++;
|
||||
}
|
||||
if (modechar == 'p') product_template = tmptemplate;
|
||||
else if (modechar == 'v') version_template = tmptemplate;
|
||||
else if (modechar == 'i') info_template = tmptemplate;
|
||||
else if (modechar == 'h') hostname_template = tmptemplate;
|
||||
else if (modechar == 'o') ostype_template = tmptemplate;
|
||||
else if (modechar == 'd') devicetype_template = tmptemplate;
|
||||
else fatal("ServiceProbeMatch::InitMatch: Unknown template specifier '%c' on line %d of nmap-service-probes", modechar, lineno);
|
||||
|
||||
matchtext = p + 1;
|
||||
}
|
||||
|
||||
isInitialized = 1;
|
||||
@@ -445,6 +440,9 @@ const struct MatchDetails *ServiceProbeMatch::testMatch(const u8 *buf, int bufle
|
||||
static char product[80];
|
||||
static char version[80];
|
||||
static char info[128];
|
||||
static char hostname[80];
|
||||
static char ostype[32];
|
||||
static char devicetype[32];
|
||||
char *bufc = (char *) buf;
|
||||
int ovector[150]; // allows 50 substring matches (including the overall match)
|
||||
assert(isInitialized);
|
||||
@@ -469,10 +467,14 @@ const struct MatchDetails *ServiceProbeMatch::testMatch(const u8 *buf, int bufle
|
||||
} else {
|
||||
// Yeah! Match apparently succeeded.
|
||||
// Now lets get the version number if available
|
||||
i = getVersionStr(buf, buflen, ovector, rc, product, sizeof(product), version, sizeof(version), info, sizeof(info));
|
||||
i = getVersionStr(buf, buflen, ovector, rc, product, sizeof(product), version, sizeof(version), info, sizeof(info),
|
||||
hostname, sizeof(hostname), ostype, sizeof(ostype), devicetype, sizeof(devicetype));
|
||||
if (*product) MD_return.product = product;
|
||||
if (*version) MD_return.version = version;
|
||||
if (*info) MD_return.info = info;
|
||||
if (*hostname) MD_return.hostname = hostname;
|
||||
if (*ostype) MD_return.ostype = ostype;
|
||||
if (*devicetype) MD_return.devicetype = devicetype;
|
||||
|
||||
MD_return.serviceName = servicename;
|
||||
}
|
||||
@@ -734,22 +736,28 @@ static int dotmplsubst(const u8 *subject, int subjectlen,
|
||||
}
|
||||
|
||||
|
||||
// Use the three version templates, and the match data included here
|
||||
// to put the version info into 'product', 'version', and 'info',
|
||||
// (as long as the given string sizes are sufficient). Returns zero
|
||||
// for success. If no template is available for product, version,
|
||||
// and/or info, that string will have zero length after the function
|
||||
// Use the six version templates and the match data included here
|
||||
// to put the version info into the given strings, (as long as the sizes
|
||||
// are sufficient). Returns zero for success. If no template is available
|
||||
// for a string, that string will have zero length after the function
|
||||
// call (assuming the corresponding length passed in is at least 1)
|
||||
|
||||
int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen,
|
||||
int *ovector, int nummatches, char *product, int productlen,
|
||||
char *version, int versionlen, char *info, int infolen) {
|
||||
char *version, int versionlen, char *info, int infolen,
|
||||
char *hostname, int hostnamelen, char *ostype, int ostypelen,
|
||||
char *devicetype, int devicetypelen) {
|
||||
|
||||
int rc;
|
||||
assert(productlen >= 0 && versionlen >= 0 && infolen >= 0);
|
||||
assert(productlen >= 0 && versionlen >= 0 && infolen >= 0 &&
|
||||
hostnamelen >= 0 && ostypelen >= 0 && devicetypelen >= 0);
|
||||
|
||||
if (productlen > 0) *product = '\0';
|
||||
if (versionlen > 0) *version = '\0';
|
||||
if (infolen > 0) *info = '\0';
|
||||
if (hostnamelen > 0) *hostname = '\0';
|
||||
if (ostypelen > 0) *ostype = '\0';
|
||||
if (devicetypelen > 0) *devicetype = '\0';
|
||||
int retval = 0;
|
||||
|
||||
// Now lets get this started! We begin with the product name
|
||||
@@ -783,6 +791,33 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen,
|
||||
}
|
||||
}
|
||||
|
||||
if (hostname_template) {
|
||||
rc = dotmplsubst(subject, subjectlen, ovector, nummatches, hostname_template, hostname, hostnamelen);
|
||||
if (rc != 0) {
|
||||
error("Warning: Servicescan failed to fill hostname_template (subjectlen: %d). Too long? Match string was line %d: h/%s/", subjectlen, deflineno, (hostname_template)? hostname_template : "");
|
||||
if (hostnamelen > 0) *hostname = '\0';
|
||||
retval = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ostype_template) {
|
||||
rc = dotmplsubst(subject, subjectlen, ovector, nummatches, ostype_template, ostype, ostypelen);
|
||||
if (rc != 0) {
|
||||
error("Warning: Servicescan failed to fill ostype_template (subjectlen: %d). Too long? Match string was line %d: p/%s/", subjectlen, deflineno, (ostype_template)? ostype_template : "");
|
||||
if (ostypelen > 0) *ostype = '\0';
|
||||
retval = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (devicetype_template) {
|
||||
rc = dotmplsubst(subject, subjectlen, ovector, nummatches, devicetype_template, devicetype, devicetypelen);
|
||||
if (rc != 0) {
|
||||
error("Warning: Servicescan failed to fill devicetype_template (subjectlen: %d). Too long? Match string was line %d: d/%s/", subjectlen, deflineno, (devicetype_template)? devicetype_template : "");
|
||||
if (devicetypelen > 0) *devicetype = '\0';
|
||||
retval = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1161,6 +1196,7 @@ ServiceNFO::ServiceNFO(AllProbes *newAP) {
|
||||
currentresplen = 0;
|
||||
port = NULL;
|
||||
product_matched[0] = version_matched[0] = extrainfo_matched[0] = '\0';
|
||||
hostname_matched[0] = ostype_matched[0] = devicetype_matched[0] = '\0';
|
||||
tunnel = SERVICE_TUNNEL_NONE;
|
||||
ssl_session = NULL;
|
||||
softMatchFound = false;
|
||||
@@ -1659,6 +1695,7 @@ static int scanThroughTunnel(nsock_pool nsp, nsock_iod nsi, ServiceGroup *SG,
|
||||
svc->tunnel = SERVICE_TUNNEL_SSL;
|
||||
svc->probe_matched = NULL;
|
||||
svc->product_matched[0] = svc->version_matched[0] = svc->extrainfo_matched[0] = '\0';
|
||||
svc->hostname_matched[0] = svc->ostype_matched[0] = svc->devicetype_matched[0] = '\0';
|
||||
svc->softMatchFound = false;
|
||||
svc->resetProbes(true);
|
||||
startNextProbe(nsp, nsi, SG, svc, true);
|
||||
@@ -1903,6 +1940,12 @@ void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
|
||||
Strncpy(svc->version_matched, MD->version, sizeof(svc->version_matched));
|
||||
if (MD->info)
|
||||
Strncpy(svc->extrainfo_matched, MD->info, sizeof(svc->extrainfo_matched));
|
||||
if (MD->hostname)
|
||||
Strncpy(svc->hostname_matched, MD->hostname, sizeof(svc->hostname_matched));
|
||||
if (MD->ostype)
|
||||
Strncpy(svc->ostype_matched, MD->ostype, sizeof(svc->ostype_matched));
|
||||
if (MD->devicetype)
|
||||
Strncpy(svc->devicetype_matched, MD->devicetype, sizeof(svc->devicetype_matched));
|
||||
svc->softMatchFound = MD->isSoft;
|
||||
if (!svc->softMatchFound) {
|
||||
// We might be able to continue scan through a tunnel protocol
|
||||
@@ -2021,19 +2064,22 @@ list<ServiceNFO *>::iterator svc;
|
||||
*(*svc)->product_matched? (*svc)->product_matched : NULL,
|
||||
*(*svc)->version_matched? (*svc)->version_matched : NULL,
|
||||
*(*svc)->extrainfo_matched? (*svc)->extrainfo_matched : NULL,
|
||||
*(*svc)->hostname_matched? (*svc)->hostname_matched : NULL,
|
||||
*(*svc)->ostype_matched? (*svc)->ostype_matched : NULL,
|
||||
*(*svc)->devicetype_matched? (*svc)->devicetype_matched : NULL,
|
||||
NULL);
|
||||
|
||||
} else if ((*svc)->probe_state == PROBESTATE_FINISHED_SOFTMATCHED) {
|
||||
(*svc)->port->setServiceProbeResults((*svc)->probe_state,
|
||||
(*svc)->probe_matched,
|
||||
(*svc)->tunnel,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
(*svc)->getServiceFingerprint(NULL));
|
||||
|
||||
} else if ((*svc)->probe_state == PROBESTATE_FINISHED_NOMATCH) {
|
||||
if ((*svc)->getServiceFingerprint(NULL))
|
||||
(*svc)->port->setServiceProbeResults((*svc)->probe_state, NULL,
|
||||
(*svc)->tunnel, NULL, NULL, NULL,
|
||||
(*svc)->tunnel, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
(*svc)->getServiceFingerprint(NULL));
|
||||
}
|
||||
}
|
||||
@@ -2120,8 +2166,10 @@ void remove_excluded_ports(AllProbes *AP, ServiceGroup *SG) {
|
||||
|
||||
if (o.debugging) printf("EXCLUDING %d/%s\n", svc->portno, svc->proto==IPPROTO_TCP ? "tcp" : "udp");
|
||||
|
||||
svc->port->setServiceProbeResults(PROBESTATE_EXCLUDED, NULL, SERVICE_TUNNEL_NONE,
|
||||
"Excluded from version scan", NULL, NULL, NULL);
|
||||
svc->port->setServiceProbeResults(PROBESTATE_EXCLUDED, NULL,
|
||||
SERVICE_TUNNEL_NONE,
|
||||
"Excluded from version scan", NULL,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
SG->services_remaining.erase(i);
|
||||
SG->services_finished.push_back(svc);
|
||||
|
||||
@@ -140,6 +140,11 @@ struct MatchDetails {
|
||||
const char *product;
|
||||
const char *version;
|
||||
const char *info;
|
||||
|
||||
// More information from a match. Zero-terminated strings or NULL.
|
||||
const char *hostname;
|
||||
const char *ostype;
|
||||
const char *devicetype;
|
||||
};
|
||||
|
||||
/********************** CLASSES ***********************************/
|
||||
@@ -189,21 +194,26 @@ class ServiceProbeMatch {
|
||||
char *product_template;
|
||||
char *version_template;
|
||||
char *info_template;
|
||||
// More templates:
|
||||
char *hostname_template;
|
||||
char *ostype_template;
|
||||
char *devicetype_template;
|
||||
// The anchor is for SERVICESCAN_STATIC matches. If the anchor is not -1, the match must
|
||||
// start at that zero-indexed position in the response str.
|
||||
int matchops_anchor;
|
||||
// Details to fill out and return for testMatch() calls
|
||||
struct MatchDetails MD_return;
|
||||
|
||||
// Use the three version templates, and the match data included here
|
||||
// to put the version info into 'product', 'version', and 'info',
|
||||
// (as long as the given string sizes are sufficient). Returns zero
|
||||
// for success. If no template is available for product, version,
|
||||
// and/or info, that string will have zero length after the function
|
||||
// Use the six version templates and the match data included here
|
||||
// to put the version info into the given strings, (as long as the sizes
|
||||
// are sufficient). Returns zero for success. If no template is available
|
||||
// for a string, that string will have zero length after the function
|
||||
// call (assuming the corresponding length passed in is at least 1)
|
||||
int getVersionStr(const u8 *subject, int subjectlen, int *ovector,
|
||||
int nummatches, char *product, int productlen,
|
||||
char *version, int versionlen, char *info, int infolen);
|
||||
char *version, int versionlen, char *info, int infolen,
|
||||
char *hostname, int hostnamelen, char *ostype, int ostypelen,
|
||||
char *devicetype, int devicetypelen);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -192,10 +192,10 @@ void adjust_timeouts2(const struct timeval *sent,
|
||||
log_write(LOG_STDOUT, "delta %ld ==> srtt: %d rttvar: %d to: %d\n", delta, to->srtt, to->rttvar, to->timeout);
|
||||
}
|
||||
|
||||
if (to->srtt < 0 || to->rttvar < 0 || to->timeout < 0 || delta < -50000000 ||
|
||||
/* if (to->srtt < 0 || to->rttvar < 0 || to->timeout < 0 || delta < -50000000 ||
|
||||
sent->tv_sec == 0 || received->tv_sec == 0 ) {
|
||||
fatal("Serious time computation problem in adjust_timeout ... received = (%ld, %ld) sent=(%ld,%ld) delta = %ld srtt = %d rttvar = %d to = %d", (long) received->tv_sec, (long)received->tv_usec, (long) sent->tv_sec, (long) sent->tv_usec, delta, to->srtt, to->rttvar, to->timeout);
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
/* Sleeps if necessary to ensure that it isn't called twice withen less
|
||||
|
||||
Reference in New Issue
Block a user