1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-22 15:39:03 +00:00

merge soc07 r4727 - Added --top-ports/--port-ratio and wildcard/[] -p switch extensions.

This commit is contained in:
fyodor
2007-08-11 02:58:03 +00:00
parent 510eba5dd2
commit e51abafe02
9 changed files with 528 additions and 258 deletions

View File

@@ -192,6 +192,7 @@ void NmapOps::Initialize() {
randomize_hosts = 0;
sendpref = PACKET_SEND_NOPREF;
spoofsource = 0;
fastscan = 0;
device[0] = '\0';
interactivemode = 0;
ping_group_sz = PING_GROUP_SZ;
@@ -261,6 +262,7 @@ void NmapOps::Initialize() {
ipopt_firsthop = 0;
ipopt_lasthop = 0;
release_memory = false;
topportlevel = -1;
#ifndef NOLUA
script = 0;
scriptversion = 0;

View File

@@ -172,6 +172,7 @@ class NmapOps {
int verbose;
int randomize_hosts;
int spoofsource; /* -S used */
int fastscan;
char device[64];
int interactivemode;
int ping_group_sz;
@@ -191,6 +192,7 @@ class NmapOps {
int timing_level; // 0-5, corresponding to Paranoid, Sneaky, Polite, Normal, Aggressive, Insane
int max_parallelism; // 0 means it has not been set
int min_parallelism; // 0 means it has not been set
double topportlevel; // -1 means it has not been set
/* The maximum number of OS detection (gen2) tries we will make
without any matches before giving up on a host. We may well give

299
nmap.cc
View File

@@ -230,8 +230,10 @@ printf("%s %s ( %s )\n"
"PORT SPECIFICATION AND SCAN ORDER:\n"
" -p <port ranges>: Only scan specified ports\n"
" Ex: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080\n"
" -F: Fast - Scan only the ports listed in the nmap-services file)\n"
" -F: Fast mode - Scan fewer ports than the default scan\n"
" -r: Scan ports consecutively - don't randomize\n"
" --top-ports <number>: Scan <number> most common ports\n"
" --port-ratio <ratio>: Scan ports more common than <ratio>\n"
"SERVICE/VERSION DETECTION:\n"
" -sV: Probe open ports to determine service/version info\n"
" --version-intensity <level>: Set from 0 (light) to 9 (try all probes)\n"
@@ -451,7 +453,7 @@ int nmap_main(int argc, char *argv[]) {
unsigned int targetno;
FILE *inputfd = NULL, *excludefd = NULL;
char *host_spec = NULL, *exclude_spec = NULL;
short fastscan=0, randomize=1;
short randomize=1;
short quashargv = 0;
char **host_exp_group;
char *idleProxy = NULL; /* The idle host used to "Proxy" an Idlescan */
@@ -600,6 +602,8 @@ int nmap_main(int argc, char *argv[]) {
{"log-errors", no_argument, 0, 0},
{"dns_servers", required_argument, 0, 0},
{"dns-servers", required_argument, 0, 0},
{"port-ratio", required_argument, 0, 0},
{"top-ports", required_argument, 0, 0},
#ifndef NOLUA
{"script", required_argument, 0, 0},
{"script-trace", no_argument, 0, 0},
@@ -829,6 +833,16 @@ int nmap_main(int argc, char *argv[]) {
o.fragscan = atoi(optarg);
if (o.fragscan <= 0 || o.fragscan % 8 != 0)
fatal("Data payload MTU must be >0 and multiple of 8");
} else if (strcmp(long_options[option_index].name, "port-ratio") == 0) {
char *ptr;
o.topportlevel = strtod(optarg, &ptr);
if (!ptr || o.topportlevel < 0 || o.topportlevel >= 1)
fatal("--port-ratio should be between [0 and 1)");
} else if (strcmp(long_options[option_index].name, "top-ports") == 0) {
char *ptr;
o.topportlevel = strtod(optarg, &ptr);
if (!ptr || o.topportlevel < 1 || ((double)((int)o.topportlevel)) != o.topportlevel)
fatal("--top-ports should be an integer 1 or greater");
} else if (optcmp(long_options[option_index].name, "ip-options") == 0){
o.ipoptions = (u8*) safe_malloc(4*10+1);
o.ipoptionslen = parse_ip_options(optarg, o.ipoptions, 4*10+1, &o.ipopt_firsthop, &o.ipopt_lasthop);
@@ -896,7 +910,7 @@ int nmap_main(int argc, char *argv[]) {
break;
case 'e':
Strncpy(o.device, optarg, sizeof(o.device)); break;
case 'F': fastscan++; break;
case 'F': o.fastscan++; break;
case 'f': o.fragscan += 8; break;
case 'g':
o.magic_port = atoi(optarg);
@@ -1202,25 +1216,29 @@ int nmap_main(int argc, char *argv[]) {
}
if ((o.pingscan || o.listscan) && (portlist || fastscan)) {
if ((o.pingscan || o.listscan) && (portlist || o.fastscan))
fatal("You cannot use -F (fast scan) or -p (explicit port selection) with PING scan or LIST scan");
if (portlist && o.fastscan)
fatal("You cannot use -F (fast scan) with -p (explicit port selection) but see --top-ports and --port-ratio to fast scan a range of ports");
if (o.ipprotscan) {
if (portlist) ports = getpts(portlist);
else ports = getpts((char *) (o.fastscan ? "[P:0-]" : "0-")); // Default protocols to scan
} else {
ports = gettoppts(o.topportlevel, portlist);
}
if (portlist && !ports)
fatal("Your port specification string is not parseable");
if (portlist) {
ports = getpts(portlist);
if (!ports)
fatal("Your port specification string is not parseable");
free(portlist);
portlist = NULL;
}
if (fastscan && ports) {
fatal("You can specify fast scan (-F) or explicitly select individual ports (-p), but not both");
} else if (fastscan && o.ipprotscan) {
ports = getfastprots();
} else if (fastscan) {
ports = getfastports(o.TCPScan(), o.UDPScan());
}
// Uncomment the following line to use the common lisp port spec test suite
//printf("port spec: (%d %d %d)\n", ports->tcp_count, ports->udp_count, ports->prot_count); exit(0);
#ifdef WIN32
if (o.sendpref & PACKET_SEND_IP) {
@@ -1274,14 +1292,6 @@ int nmap_main(int argc, char *argv[]) {
o.sendpref = PACKET_SEND_ETH_STRONG;
}
if (!ports) {
if (o.ipprotscan) {
ports = getdefaultprots();
} else {
ports = getdefaultports(o.TCPScan(), o.UDPScan());
}
}
/* By now, we've got our port lists. Give the user a warning if no
* ports are specified for the type of scan being requested. Other things
* (such as OS ident scan) might break cause no ports were specified, but
@@ -1930,19 +1940,74 @@ void init_socket(int sd) {
}
}
/* Convert a string like "-100,200-1024,3000-4000,60000-" into an array
of port numbers. Note that one trailing comma is OK -- this is actually
useful for machine generated lists */
/* Convert a string like "-100,n*tp,200-1024,3000-4000,[60000-]" into an array
* of port numbers. Note that one trailing comma is OK -- this is actually
* useful for machine generated lists
*
* Fyodor - Wrote original
* William McVey - Added T:, U:, P: directives
* Doug Hoyte - Added [], name lookups, and wildcard expansion
*
* getpts() handles []
* Any port ranges included inside square brackets will have all
* their ports looked up in nmap-services or nmap-protocols
* and will only be included if they are found.
* Returns a scan_list* with all the ports that should be scanned.
*
* getpts() handles service/protocol name lookups and wildcard expansion.
* The service name can be specified instead of the port number.
* For example, "ssh" can be used instead of "22". You can use wildcards
* like "*" and "?". See the function wildtest() for the exact details.
* For example,
*
* nmap -p http* host
*
* Will scan http (80), http-mgmt (280), http-proxy (8080), https (443), etc.
*
* Matching is case INsensitive but the first character in a match MUST
* be lowercase so it doesn't conflict with the T:, U:, and P: directives.
*
* getpts() is unable to match service names that start with a digit
* like 3com-tsmux (106/udp). Use a pattern like "?com-*" instead.
*
* BE CAREFUL ABOUT SHELL EXPANSIONS!!!
* If you are trying to match the services nmsp (537/tcp) and nms (1429/tcp)
* and you execute the command
*
* ./nmap -p nm* host
*
* You will see
*
* Found no matches for the service mask 'nmap' and your specified protocols
* QUITTING!
*
* This is because nm* was expanded to the name of the binary file nmap in
* the current directory by your shell. When unsure, quote your port strings
* to be safe:
*
* ./nmap -p 'nm*' host
*
* getpts() is smart enough to keep the T: U: and P: directives nested
* and working in a logical manner. For instance,
*
* nmap -sTU -p [U:1025-],1-1024 host
*
* Will scan UDP ports 1025 and up that are found in the service file
* and all TCP/UDP ports below <= 1024. Notice that the U doesn't affect
* the outer part of the port expression. It's "closed".
*/
static void getpts_aux(char *origexpr, int nested, u8 *porttbl, struct scan_lists *ports, int range_type, int
*portwarning);
struct scan_lists *getpts(char *origexpr) {
u8 *porttbl;
int portwarning = 0; /* have we warned idiot about dup ports yet? */
long rangestart = -2343242, rangeend = -9324423;
char *current_range;
char *endptr;
int i;
int tcpportcount = 0, udpportcount = 0, protcount = 0;
struct scan_lists *ports;
int range_type = 0;
int portwarning = 0;
int i, tcpi, udpi, proti;
if (o.TCPScan())
range_type |= SCAN_TCP_PORT;
@@ -1952,11 +2017,58 @@ struct scan_lists *getpts(char *origexpr) {
range_type |= SCAN_PROTOCOLS;
porttbl = (u8 *) safe_zalloc(65536);
ports = (struct scan_lists *) safe_zalloc(sizeof(struct scan_lists));
getpts_aux(origexpr, // Pass on the expression
0, // Don't start off nested
porttbl, // Our allocated port table
ports, // The destination structure - passed so we can track the number of tcp/udp/prot ports
range_type, // Defaults to TCP/UDP/Protos
&portwarning); // No, we haven't warned them about dup ports yet
if ( 0 == (ports->tcp_count + ports->udp_count + ports->prot_count))
fatal("No ports specified -- If you really don't want to scan any ports use ping scan...");
if (ports->tcp_count) {
ports->tcp_ports = (unsigned short *)safe_zalloc(ports->tcp_count * sizeof(unsigned short));
}
if (ports->udp_count) {
ports->udp_ports = (unsigned short *)safe_zalloc(ports->udp_count * sizeof(unsigned short));
}
if (ports->prot_count) {
ports->prots = (unsigned short *)safe_zalloc(ports->prot_count * sizeof(unsigned short));
}
for(i=tcpi=udpi=proti=0; i <= 65535; i++) {
if (porttbl[i] & SCAN_TCP_PORT)
ports->tcp_ports[tcpi++] = i;
if (porttbl[i] & SCAN_UDP_PORT)
ports->udp_ports[udpi++] = i;
if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
ports->prots[proti++] = i;
}
free(porttbl);
return ports;
}
/* getpts() (see above) is a wrapper for this function */
static void getpts_aux(char *origexpr, int nested, u8 *porttbl, struct scan_lists *ports, int range_type, int *portwarning) {
long rangestart = -2343242, rangeend = -9324423;
char *current_range;
char *endptr;
char servmask[128]; // A protocol name can be up to 127 chars + nul byte
int i;
current_range = origexpr;
do {
while(isspace((int) *current_range))
current_range++; /* I don't know why I should allow spaces here, but I will */
if (*current_range == 'T' && *++current_range == ':') {
current_range++;
range_type = SCAN_TCP_PORT;
@@ -1972,7 +2084,26 @@ struct scan_lists *getpts(char *origexpr) {
range_type = SCAN_PROTOCOLS;
continue;
}
if (*current_range == '-') {
if (*current_range == '[') {
if (nested)
fatal("Can't nest [] brackets in -p switch");
getpts_aux(++current_range, 1, porttbl, ports, range_type, portwarning);
// Skip past the ']'. This is OK because we can't nest []s
while(*current_range != ']') current_range++;
current_range++;
// Skip over a following ',' so we're ready to keep parsing
if (*current_range == ',') current_range++;
continue;
} else if (*current_range == ']') {
if (!nested)
fatal("Unexpected ] character in -p switch");
return;
} else if (*current_range == '-') {
rangestart = o.ipprotscan ? 0 : 1;
}
else if (isdigit((int) *current_range)) {
@@ -1984,21 +2115,38 @@ struct scan_lists *getpts(char *origexpr) {
if (rangestart < 0 || rangestart > 65535)
fatal("Ports to be scanned must be between 0 and 65535 inclusive");
}
/* if (rangestart == 0) {
error("WARNING: Scanning \"port 0\" is supported, but unusual.");
} */
current_range = endptr;
while(isspace((int) *current_range)) current_range++;
} else if (islower((int) *current_range) || *current_range == '*' || *current_range == '?') {
i = 0;
while (*current_range && !isspace((int)*current_range) && *current_range != ',' && *current_range != ']') {
servmask[i++] = *(current_range++);
if (i >= ((int)sizeof(servmask)-1))
fatal("A service mask in the -p switch is either malformed or too long");
}
if (*current_range && *current_range != ']') current_range++; // We want the '] character to be picked up on the next pass
servmask[i] = '\0'; // Finish the string
i = addportsfromservmask(servmask, porttbl, ports, range_type);
if (range_type & SCAN_PROTOCOLS) i += addprotocolsfromservmask(servmask, porttbl, ports);
if (i == 0)
fatal("Found no matches for the service mask '%s' and your specified protocols", servmask);
continue;
} else {
fatal("Error #485: Your port specifications are illegal. Example of proper form: \"-100,200-1024,T:3000-4000,U:60000-\"");
}
/* Now I have a rangestart, time to go after rangeend */
if (!*current_range || *current_range == ',') {
if (!*current_range || *current_range == ',' || *current_range == ']') {
/* Single port specification */
rangeend = rangestart;
} else if (*current_range == '-') {
current_range++;
if (!*current_range || *current_range == ',') {
if (!*current_range || *current_range == ',' || *current_range == ']') {
/* Ended with a -, meaning up until the last possible port */
rangeend = o.ipprotscan ? 255 : 65535;
} else if (isdigit((int) *current_range)) {
@@ -2021,24 +2169,45 @@ struct scan_lists *getpts(char *origexpr) {
/* Now I have a rangestart and a rangeend, so I can add these ports */
while(rangestart <= rangeend) {
if (porttbl[rangestart] & range_type) {
if (!portwarning) {
if (!(*portwarning)) {
error("WARNING: Duplicate port number(s) specified. Are you alert enough to be using Nmap? Have some coffee or Jolt(tm).");
portwarning++;
(*portwarning)++;
}
} else {
if (range_type & SCAN_TCP_PORT)
tcpportcount++;
if (range_type & SCAN_UDP_PORT)
udpportcount++;
if (range_type & SCAN_PROTOCOLS)
protcount++;
porttbl[rangestart] |= range_type;
if (nested) {
if ((range_type & SCAN_TCP_PORT) &&
nmap_getservbyport(htons(rangestart), "tcp")) {
ports->tcp_count++;
porttbl[rangestart] |= SCAN_TCP_PORT;
}
if ((range_type & SCAN_UDP_PORT) &&
nmap_getservbyport(htons(rangestart), "udp")) {
ports->udp_count++;
porttbl[rangestart] |= SCAN_UDP_PORT;
}
if ((range_type & SCAN_PROTOCOLS) &&
nmap_getprotbynum(htons(rangestart))) {
ports->prot_count++;
porttbl[rangestart] |= SCAN_PROTOCOLS;
}
} else {
if (range_type & SCAN_TCP_PORT)
ports->tcp_count++;
if (range_type & SCAN_UDP_PORT)
ports->udp_count++;
if (range_type & SCAN_PROTOCOLS && rangestart < 256)
ports->prot_count++;
porttbl[rangestart] |= range_type;
}
}
rangestart++;
}
/* Find the next range */
while(isspace((int) *current_range)) current_range++;
if (*current_range == ']') return;
if (*current_range && *current_range != ',') {
fatal("Error #488: Your port specifications are illegal. Example of proper form: \"-100,200-1024,3000-4000,60000-\"");
}
@@ -2046,45 +2215,13 @@ struct scan_lists *getpts(char *origexpr) {
current_range++;
} while(current_range && *current_range);
if ( 0 == (tcpportcount + udpportcount + protcount))
fatal("No ports specified -- If you really don't want to scan any ports use ping scan...");
ports = (struct scan_lists *) safe_zalloc(sizeof(struct scan_lists));
if (tcpportcount) {
ports->tcp_ports = (unsigned short *)safe_zalloc(tcpportcount * sizeof(unsigned short));
}
if (udpportcount) {
ports->udp_ports = (unsigned short *)safe_zalloc(udpportcount * sizeof(unsigned short));
}
if (protcount) {
ports->prots = (unsigned short *)safe_zalloc(protcount * sizeof(unsigned short));
}
ports->tcp_count = tcpportcount;
ports->udp_count = udpportcount;
ports->prot_count = protcount;
tcpportcount=0;
udpportcount=0;
protcount=0;
for(i=0; i <= 65535; i++) {
if (porttbl[i] & SCAN_TCP_PORT)
ports->tcp_ports[tcpportcount++] = i;
if (porttbl[i] & SCAN_UDP_PORT)
ports->udp_ports[udpportcount++] = i;
if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
ports->prots[protcount++] = i;
}
free(porttbl);
return ports;
}
void free_scan_lists(struct scan_lists *ports) {
if (ports) {
free(ports->tcp_ports);
free(ports->udp_ports);
free(ports->prots);
if (ports->tcp_ports) free(ports->tcp_ports);
if (ports->udp_ports) free(ports->udp_ports);
if (ports->prots) free(ports->prots);
free(ports);
}
}

View File

@@ -178,9 +178,40 @@ static int nmap_protocols_init() {
}
/* Adds protocols whose names match mask to porttbl.
* Increases the prot_count in ports by the number of protocols added.
* Returns the number of protocols added.
*/
int addprotocolsfromservmask(char *mask, u8 *porttbl, struct scan_lists *ports) {
struct protocol_list *current;
int bucket, t=0;
if (!protocols_initialized && nmap_protocols_init() == -1)
fatal("addprotocolsfromservmask: Couldn't get protocol numbers");
for(bucket = 0; bucket < PROTOCOL_TABLE_SIZE; bucket++) {
for(current = protocol_table[bucket % PROTOCOL_TABLE_SIZE]; current; current = current->next) {
if (wildtest(mask, current->protoent->p_name)) {
porttbl[ntohs(current->protoent->p_proto)] |= SCAN_PROTOCOLS;
ports->prot_count++;
t++;
}
}
}
return t;
}
struct protoent *nmap_getprotbynum(int num) {
struct protocol_list *current;
nmap_protocols_init();
if (nmap_protocols_init() == -1)
return NULL;
for(current = protocol_table[num % PROTOCOL_TABLE_SIZE];
current; current = current->next) {
if (num == current->protoent->p_proto)
@@ -189,61 +220,4 @@ struct protoent *nmap_getprotbynum(int num) {
/* Couldn't find it ... oh well. */
return NULL;
}
/* By default we do all prots 0-255. */
struct scan_lists *getdefaultprots(void) {
int protindex = 0;
struct scan_lists *scanlist;
/*struct protocol_list *current;*/
int bucket;
int protsneeded = 256;
if (nmap_protocols_init() == -1)
fatal("getdefaultprots(): Couldn't get protocol numbers");
scanlist = (struct scan_lists *) safe_zalloc(sizeof(struct scan_lists));
scanlist->prots = (unsigned short *) safe_zalloc((protsneeded) * sizeof(unsigned short));
scanlist->prot_count = protsneeded;
for(bucket = 0; bucket < protsneeded; bucket++) {
scanlist->prots[protindex++] = bucket;
}
return scanlist;
}
struct scan_lists *getfastprots(void) {
int protindex = 0;
struct scan_lists *scanlist;
char usedprots[256];
struct protocol_list *current;
int bucket;
int protsneeded = 0;
if (nmap_protocols_init() == -1)
fatal("Getfastprots: Couldn't get protocol numbers");
memset(usedprots, 0, sizeof(usedprots));
for(bucket = 0; bucket < PROTOCOL_TABLE_SIZE; bucket++) {
for(current = protocol_table[bucket % PROTOCOL_TABLE_SIZE];
current; current = current->next) {
if (!usedprots[ntohs(current->protoent->p_proto)])
usedprots[ntohs(current->protoent->p_proto)] = 1;
protsneeded++;
}
}
scanlist = (struct scan_lists *) safe_zalloc(sizeof(struct scan_lists));
scanlist->prots = (unsigned short *) safe_zalloc((protsneeded ) * sizeof(unsigned short));
scanlist->prot_count = protsneeded;
for(bucket = 0; bucket < 256; bucket++) {
if (usedprots[bucket])
scanlist->prots[protindex++] = bucket;
}
return scanlist;
}

View File

@@ -119,9 +119,7 @@ struct protocol_list {
struct protocol_list *next;
};
int addprotocolsfromservmask(char *mask, u8 *porttbl, struct scan_lists *ports);
struct protoent *nmap_getprotbynum(int num);
struct scan_lists *getfastprots(void);
struct scan_lists *getdefaultprots(void);
#endif

View File

@@ -106,9 +106,11 @@ extern NmapOps o;
static int numtcpports = 0;
static int numudpports = 0;
static struct service_list *service_table[SERVICE_TABLE_SIZE];
static struct service_list *sorted_services = NULL;
static int services_initialized = 0;
static int ratio_format = 0; // 0 = /etc/services no-ratio format. 1 = new nmap format
static int nmap_services_init() {
static int services_initialized = 0;
if (services_initialized) return 0;
char filename[512];
@@ -118,8 +120,10 @@ static int nmap_services_init() {
char *p;
char line[1024];
int lineno = 0;
struct service_list *current, *previous;
struct service_list *current, *previous, *sp;
int res;
double ratio;
int ratio_n, ratio_d;
if (nmap_fetchfile(filename, sizeof(filename), "nmap-services") != 1) {
#ifndef WIN32
@@ -159,12 +163,27 @@ static int nmap_services_init() {
p++;
if (*p == '#')
continue;
res = sscanf(line, "%127s %hu/%15s", servicename, &portno, proto);
if (res !=3)
res = sscanf(line, "%127s %hu/%15s %d/%d", servicename, &portno, proto, &ratio_n, &ratio_d);
if (res == 3) {
ratio = 0;
} else if (res == 5) {
if (ratio_n > ratio_d)
fatal("%s:%d has a ratio %g. All ratios must be < 1", filename, lineno, (double)ratio_n/ratio_d);
if (ratio_d == 0)
fatal("%s:%d has a ratio denominator of 0 causing a division by 0 error", filename, lineno);
ratio = (double)ratio_n / ratio_d;
ratio_format = 1;
} else {
continue;
}
portno = htons(portno);
/* Now we make sure our services doesn't have duplicates */
/* Now we make sure our service table doesn't have duplicates */
for(current = service_table[portno % SERVICE_TABLE_SIZE], previous = NULL;
current; current = current->next) {
if (portno == (u16) current->servent->s_port &&
@@ -198,6 +217,7 @@ static int nmap_services_init() {
current = (struct service_list *) cp_alloc(sizeof(struct service_list));
current->servent = (struct servent *) cp_alloc(sizeof(struct servent));
current->ratio = ratio;
current->next = NULL;
if (previous == NULL) {
service_table[portno % SERVICE_TABLE_SIZE] = current;
@@ -208,13 +228,75 @@ static int nmap_services_init() {
current->servent->s_port = portno;
current->servent->s_proto = cp_strdup(proto);
current->servent->s_aliases = NULL;
sp = (struct service_list *) cp_alloc(sizeof(struct service_list));
sp->servent = current->servent;
sp->ratio = current->ratio;
sp->next = NULL;
if (sorted_services == NULL || sorted_services->ratio < sp->ratio) {
sp->next = sorted_services;
sorted_services = sp;
} else
for (current=sorted_services;;current=current->next) {
if (current->next == NULL) {
current->next = sp;
break;
} else if (current->next->ratio < sp->ratio) {
sp->next = current->next;
current->next = sp;
break;
}
}
}
fclose(fp);
services_initialized = 1;
return 0;
}
/* Adds ports whose names match mask and one or more protocols
* specified by range_type to porttbl. Increases the respective
* protocol counts in ports.
* Returns the number of ports added in total.
*/
int addportsfromservmask(char *mask, u8 *porttbl, struct scan_lists *ports, int range_type) {
struct service_list *current;
int bucket,t=0;
if (!services_initialized && nmap_services_init() == -1)
fatal("addportsfromservmask: Couldn't get port numbers");
for(bucket = 0; bucket < SERVICE_TABLE_SIZE; bucket++) {
for(current = service_table[bucket % SERVICE_TABLE_SIZE]; current; current = current->next) {
if (wildtest(mask, current->servent->s_name)) {
if ((range_type & SCAN_TCP_PORT) && strcmp(current->servent->s_proto, "tcp") == 0) {
porttbl[ntohs(current->servent->s_port)] |= SCAN_TCP_PORT;
ports->tcp_count++;
t++;
}
if ((range_type & SCAN_UDP_PORT) && strcmp(current->servent->s_proto, "udp") == 0) {
porttbl[ntohs(current->servent->s_port)] |= SCAN_UDP_PORT;
ports->udp_count++;
t++;
}
}
}
}
return t;
}
struct servent *nmap_getservbyport(int port, const char *proto) {
struct service_list *current;
@@ -222,7 +304,7 @@ struct servent *nmap_getservbyport(int port, const char *proto) {
return NULL;
for(current = service_table[port % SERVICE_TABLE_SIZE];
current; current = current->next) {
current; current = current->next) {
if (((u16) port == (u16) current->servent->s_port) &&
strcmp(proto, current->servent->s_proto) == 0)
return current->servent;
@@ -233,120 +315,149 @@ struct servent *nmap_getservbyport(int port, const char *proto) {
}
/* Be default we do all ports 1-1024 as well as any higher ports
that are in the services file */
struct scan_lists *getdefaultports(int tcpscan, int udpscan) {
int tcpportindex = 0;
int udpportindex = 0;
struct scan_lists *ports;
u8 *usedports;
struct service_list *current;
int bucket;
int tcpportsneeded = 0;
int udpportsneeded = 0;
if (nmap_services_init() == -1)
fatal("Getfastports: Couldn't get port numbers");
usedports = (u8 *) safe_zalloc(sizeof(*usedports) * 65536);
for(bucket = 1; bucket < 1025; bucket++) {
if (tcpscan) {
usedports[bucket] |= SCAN_TCP_PORT;
tcpportsneeded++;
}
if (udpscan) {
usedports[bucket] |= SCAN_UDP_PORT;
udpportsneeded++;
}
}
for(bucket = 0; bucket < SERVICE_TABLE_SIZE; bucket++) {
for(current = service_table[bucket % SERVICE_TABLE_SIZE];
current; current = current->next) {
if (tcpscan &&
! (usedports[ntohs(current->servent->s_port)] & SCAN_TCP_PORT) &&
! strncmp(current->servent->s_proto, "tcp", 3)) {
usedports[ntohs(current->servent->s_port)] |= SCAN_TCP_PORT;
tcpportsneeded++;
}
if (udpscan &&
! (usedports[ntohs(current->servent->s_port)] & SCAN_UDP_PORT) &&
!strncmp(current->servent->s_proto, "udp", 3)) {
usedports[ntohs(current->servent->s_port)] |= SCAN_UDP_PORT;
udpportsneeded++;
}
}
}
ports = (struct scan_lists *) safe_zalloc(sizeof(struct scan_lists));
if (tcpscan)
ports->tcp_ports = (unsigned short *) safe_zalloc((tcpportsneeded) * sizeof(unsigned short));
if (udpscan)
ports->udp_ports = (unsigned short *) safe_zalloc((udpportsneeded) * sizeof(unsigned short));
ports->tcp_count= tcpportsneeded;
ports->udp_count= udpportsneeded;
for(bucket = 0; bucket < 65536; bucket++) {
if (usedports[bucket] & SCAN_TCP_PORT)
ports->tcp_ports[tcpportindex++] = bucket;
if (usedports[bucket] & SCAN_UDP_PORT)
ports->udp_ports[udpportindex++] = bucket;
}
free(usedports);
return ports;
static int port_compare(const void *a, const void *b) {
unsigned short ua = *((unsigned short *) a), ub = *((unsigned short *) b);
if (ua > ub) return 1;
else return -1;
}
struct scan_lists *getfastports(int tcpscan, int udpscan) {
int tcpportindex = 0;
int udpportindex = 0;
struct scan_lists *ports;
u8 *usedports;
struct service_list *current;
int bucket;
int tcpportsneeded = 0;
int udpportsneeded = 0;
if (nmap_services_init() == -1)
fatal("Getfastports: Couldn't get port numbers");
usedports = (u8 *) safe_zalloc(sizeof(*usedports) * 65536);
// is_port_member() returns true if serv is an element of ptsdata.
// This could be implemented MUCH more efficiently but it should only be
// called when you use a non-default top-ports or port-ratio value TOGETHER WITH
// a -p portlist.
for(bucket = 0; bucket < SERVICE_TABLE_SIZE; bucket++) {
for(current = service_table[bucket % SERVICE_TABLE_SIZE];
current; current = current->next) {
if (tcpscan &&
! (usedports[ntohs(current->servent->s_port)] & SCAN_TCP_PORT) &&
!strncmp(current->servent->s_proto, "tcp", 3)) {
usedports[ntohs(current->servent->s_port)] |= SCAN_TCP_PORT;
tcpportsneeded++;
}
if (udpscan &&
! (usedports[ntohs(current->servent->s_port)] & SCAN_UDP_PORT) &&
!strncmp(current->servent->s_proto, "udp", 3)) {
usedports[ntohs(current->servent->s_port)] |= SCAN_UDP_PORT;
udpportsneeded++;
}
}
static int is_port_member(struct scan_lists *ptsdata, struct service_list *serv) {
int i;
if (serv->servent->s_proto[0] == 't') {
for (i=0; i<ptsdata->tcp_count; i++)
if (ntohs(serv->servent->s_port) == ptsdata->tcp_ports[i]) return 1;
} else {
for (i=0; i<ptsdata->udp_count; i++)
if (ntohs(serv->servent->s_port) == ptsdata->udp_ports[i]) return 1;
}
ports = (struct scan_lists *) safe_zalloc(sizeof(struct scan_lists));
if (tcpscan)
ports->tcp_ports = (unsigned short *) safe_zalloc((tcpportsneeded) * sizeof(unsigned short));
if (udpscan)
ports->udp_ports = (unsigned short *) safe_zalloc((udpportsneeded) * sizeof(unsigned short));
ports->tcp_count= tcpportsneeded;
ports->udp_count= udpportsneeded;
for(bucket = 0; bucket < 65536; bucket++) {
if (usedports[bucket] & SCAN_TCP_PORT)
ports->tcp_ports[tcpportindex++] = bucket;
if (usedports[bucket] & SCAN_UDP_PORT)
ports->udp_ports[udpportindex++] = bucket;
}
free(usedports);
return ports;
return 0;
}
// gettoppts() returns a scan_list with the most common ports scanned by
// Nmap according to the ratios specified in the nmap-services file.
//
// If level is below 1.0 then we treat it as a minimum ratio and we
// add all ports with ratios above level.
//
// If level is 1 or above, we treat it as a "top ports" directive
// and return the N highest ratio ports (where N==level).
//
// This function doesn't support IP protocol scan so only call this
// function if o.TCPScan() || o.UDPScan()
struct scan_lists *gettoppts(double level, char *portlist) {
int ti=0, ui=0;
struct scan_lists *sl, *ptsdata=NULL;
struct service_list *current;
if (!services_initialized && nmap_services_init() == -1)
fatal("gettoppts: Couldn't get port numbers");
if (ratio_format == 0) {
if (level != -1)
fatal("Unable to use --top-ports or --port-ratio with an old style (no-ratio) services file");
if (portlist)
return getpts(portlist);
else if (o.fastscan)
return getpts("[-]");
else
return getpts("1-1024,[1025-]");
}
// TOP PORT DEFAULTS
if (level == -1) {
if (portlist)
return getpts(portlist);
if (o.fastscan) level = 100;
else level = 0.01;
}
sl = (struct scan_lists *) safe_zalloc(sizeof(struct scan_lists));
if (portlist) ptsdata = getpts(portlist);
if (level < 1) {
for (current=sorted_services; current; current=current->next) {
if (ptsdata && !is_port_member(ptsdata, current)) continue;
if (current->ratio >= level) {
if (o.TCPScan() && current->servent->s_proto[0] == 't') sl->tcp_count++;
else if (o.UDPScan() && current->servent->s_proto[0] == 'u') sl->udp_count++;
} else break;
}
if (sl->tcp_count)
sl->tcp_ports = (unsigned short *)safe_zalloc(sl->tcp_count * sizeof(unsigned short));
if (sl->udp_count)
sl->udp_ports = (unsigned short *)safe_zalloc(sl->udp_count * sizeof(unsigned short));
sl->prots = NULL;
for (current=sorted_services;current;current=current->next) {
if (ptsdata && !is_port_member(ptsdata, current)) continue;
if (current->ratio >= level) {
if (o.TCPScan() && current->servent->s_proto[0] == 't')
sl->tcp_ports[ti++] = ntohs(current->servent->s_port);
else if (o.UDPScan() && current->servent->s_proto[0] == 'u')
sl->udp_ports[ui++] = ntohs(current->servent->s_port);
} else break;
}
} else if (level >= 1) {
if (level > 65536)
fatal("Level argument to gettoppts (%g) is too large", level);
if (o.TCPScan()) {
sl->tcp_count = MIN((int) level, numtcpports);
sl->tcp_ports = (unsigned short *)safe_zalloc(sl->tcp_count * sizeof(unsigned short));
}
if (o.UDPScan()) {
sl->udp_count = MIN((int) level, numudpports);
sl->udp_ports = (unsigned short *)safe_zalloc(sl->udp_count * sizeof(unsigned short));
}
sl->prots = NULL;
for (current=sorted_services;current && (ti < sl->tcp_count || ui < sl->udp_count);current=current->next) {
if (ptsdata && !is_port_member(ptsdata, current)) continue;
if (o.TCPScan() && current->servent->s_proto[0] == 't' && ti < sl->tcp_count)
sl->tcp_ports[ti++] = ntohs(current->servent->s_port);
else if (o.UDPScan() && current->servent->s_proto[0] == 'u' && ui < sl->udp_count)
sl->udp_ports[ui++] = ntohs(current->servent->s_port);
}
if (ti < sl->tcp_count) sl->tcp_count = ti;
if (ui < sl->udp_count) sl->udp_count = ui;
} else
fatal("Argument to gettoppts (%g) should be a positive ratio below 1 or an integer of 1 or higher", level);
if (ptsdata) free_scan_lists(ptsdata);
if (sl->tcp_count > 1)
qsort(sl->tcp_ports, sl->tcp_count, sizeof(unsigned short), &port_compare);
if (sl->udp_count > 1)
qsort(sl->udp_ports, sl->udp_count, sizeof(unsigned short), &port_compare);
if (o.debugging && level < 1)
log_write(LOG_STDOUT, "PORTS: Using ports open on %g%% or more average hosts (TCP:%d, UDP:%d)\n", level*100, sl->tcp_count, sl->udp_count);
else if (o.debugging && level >= 1)
log_write(LOG_STDOUT, "PORTS: Using top %d ports found open (TCP:%d, UDP:%d)\n", (int) level, sl->tcp_count, sl->udp_count);
return sl;
}

View File

@@ -125,11 +125,12 @@
struct service_list {
struct servent *servent;
double ratio;
struct service_list *next;
};
int addportsfromservmask(char *mask, u8 *porttbl, struct scan_lists *ports, int range_type);
struct servent *nmap_getservbyport(int port, const char *proto);
struct scan_lists *getfastports(int tcpscan, int udpscan);
struct scan_lists *getdefaultports(int tcpscan, int udpscan);
struct scan_lists *gettoppts(double level, char *portlist);
#endif

View File

@@ -105,6 +105,49 @@
extern NmapOps o;
/* Test a wildcard mask against a test string. Wildcard mask
* can include '*' and '?' which work the same as they do
* in /bin/sh (except it's case insensitive)
* Return val of 1 means it DID match. 0 means it DIDN'T
* - Doug Hoyte, 2005
*/
int wildtest(char *wild, char *test) {
int i;
while(*wild != '\0' || *test != '\0') {
if (*wild == '*') {
/* --- Deal with multiple asterisks. --- */
while (wild[1] == '*') wild++;
/* --- Deal with terminating asterisks. --- */
if (wild[1] == '\0') return 1;
for(i=0; test[i]!='\0'; i++)
if ((wild[1] == test[i] || wild[1] == '?')
&& wildtest(wild+1, test+i) == 1) return 1;
return 0;
}
/* --- '?' can't match '\0'. --- */
if (*wild == '?' && *test == '\0') return 0;
if (*wild != '?' && tolower((int)*wild) != tolower((int)*test)) return 0;
wild++; test++;
}
if (tolower((int)*wild) == tolower((int)*test)) return 1;
return 0;
}
/* Hex dump */
void hdump(unsigned char *packet, unsigned int len) {
unsigned int i=0, j=0;

View File

@@ -189,6 +189,8 @@ template<class T> T box(T bmin, T bmax, T bnum) {
return bnum;
}
int wildtest(char *wild, char *test);
void hdump(unsigned char *packet, unsigned int len);
void lamont_hdump(char *cp, unsigned int length);