1
0
mirror of https://github.com/nmap/nmap.git synced 2026-01-24 07:09:01 +00:00

Added --exclude-ports option to Nmap

This commit is contained in:
jay
2014-07-04 05:47:11 +00:00
parent e63eb7211e
commit 3b59b0ae16
8 changed files with 126 additions and 9 deletions

View File

@@ -167,6 +167,10 @@ NmapOps::~NmapOps() {
free(portlist);
portlist = NULL;
}
if (exclude_portlist) {
free(exclude_portlist);
exclude_portlist = NULL;
}
if (proxy_chain) {
nsock_proxychain_delete(proxy_chain);
proxy_chain = NULL;
@@ -382,6 +386,7 @@ void NmapOps::Initialize() {
inputfd = NULL;
idleProxy = NULL;
portlist = NULL;
exclude_portlist = NULL;
proxy_chain = NULL;
}

View File

@@ -372,6 +372,7 @@ class NmapOps {
char *exclude_spec;
FILE *inputfd;
char *portlist; /* Ports list specified by user */
char *exclude_portlist; /* exclude-ports list specified by user */
nsock_proxychain proxy_chain;

109
nmap.cc
View File

@@ -255,6 +255,7 @@ static void printusage(int rc) {
"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,S:9\n"
" --exclude-ports <port ranges>: Exclude the specified ports from scanning\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"
@@ -638,6 +639,8 @@ void parse_options(int argc, char **argv) {
{"dns-servers", required_argument, 0, 0},
{"port-ratio", required_argument, 0, 0},
{"port_ratio", required_argument, 0, 0},
{"exclude-ports", required_argument, 0, 0},
{"exclude_ports", required_argument, 0, 0},
{"top-ports", required_argument, 0, 0},
{"top_ports", required_argument, 0, 0},
#ifndef NOLUA
@@ -941,6 +944,10 @@ void parse_options(int argc, char **argv) {
o.topportlevel = strtod(optarg, &ptr);
if (!ptr || o.topportlevel < 0 || o.topportlevel >= 1)
fatal("--port-ratio should be between [0 and 1)");
} else if (optcmp(long_options[option_index].name, "exclude-ports") == 0) {
if (o.exclude_portlist)
fatal("Only 1 --exclude-ports option allowed, separate multiple ranges with commas.");
o.exclude_portlist = strdup(optarg);
} else if (optcmp(long_options[option_index].name, "top-ports") == 0) {
char *ptr;
o.topportlevel = strtod(optarg, &ptr);
@@ -1495,7 +1502,7 @@ void apply_delayed_options() {
else
getpts((char *) (o.fastscan ? "[P:0-]" : "0-"), &ports); // Default protocols to scan
} else if (!o.noportscan) {
gettoppts(o.topportlevel, o.portlist, &ports);
gettoppts(o.topportlevel, o.portlist, &ports, o.exclude_portlist);
}
// Uncomment the following line to use the common lisp port spec test suite
@@ -1560,6 +1567,9 @@ void apply_delayed_options() {
/* Warn if setuid/setgid. */
check_setugid();
/* Remove any ports that are in the exclusion list */
removepts(o.exclude_portlist, &ports);
/* 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
@@ -1574,6 +1584,16 @@ void apply_delayed_options() {
if (o.ipprotscan && ports.prot_count == 0)
error("WARNING: protocol scan was requested, but no protocols were specified to be scanned. Skipping this scan type.");
if (o.pingtype & PINGTYPE_TCP && ports.syn_ping_count+ports.ack_ping_count == 0)
error("WARNING: a TCP ping scan was requested, but after excluding requested TCP ports, none remain. Skipping this scan type.");
if (o.pingtype & PINGTYPE_UDP && ports.udp_ping_count == 0)
error("WARNING: a UDP ping scan was requested, but after excluding requested UDP ports, none remain. Skipping this scan type.");
if (o.pingtype & PINGTYPE_SCTP_INIT && ports.sctp_ping_count == 0)
error("WARNING: a SCTP ping scan was requested, but after excluding requested SCTP ports, none remain. Skipping this scan type.");
if (o.pingtype & PINGTYPE_PROTO && ports.proto_ping_count == 0)
error("WARNING: a IP Protocol ping scan was requested, but after excluding requested protocols, none remain. Skipping this scan type.");
/* Set up our array of decoys! */
if (o.decoyturn == -1) {
o.decoyturn = (o.numdecoys == 0) ? 0 : get_random_uint() % o.numdecoys;
@@ -2379,6 +2399,11 @@ void getpts(const char *origexpr, struct scan_lists *ports) {
range_type |= SCAN_SCTP_PORT;
if (o.ipprotscan)
range_type |= SCAN_PROTOCOLS;
if (o.noportscan && o.exclude_portlist) { // We want to exclude from ping scans in this case but we take port list normally and then removepts() handles it
range_type |= SCAN_TCP_PORT;
range_type |= SCAN_UDP_PORT;
range_type |= SCAN_SCTP_PORT;
}
porttbl = (u8 *) safe_zalloc(65536);
@@ -2475,6 +2500,80 @@ void getpts_simple(const char *origexpr, int range_type,
free(porttbl);
}
/* removepts() takes a port specification and removes any matching ports
from the given scan_lists struct. */
static int remaining_ports(unsigned short int *ports, int count, unsigned short int *exclude_ports, int exclude_count, const char *type = "");
void removepts(const char *expr, struct scan_lists * ports) {
static struct scan_lists exclude_ports;
if (!expr)
return;
getpts(expr, &exclude_ports);
#define SUBTRACT_PORTS(type,excludetype) \
ports->type##_count = remaining_ports(ports->type##_ports, \
ports->type##_count, \
exclude_ports.excludetype##_ports, \
exclude_ports.excludetype##_count, \
#type)
SUBTRACT_PORTS(tcp, tcp);
SUBTRACT_PORTS(udp, udp);
SUBTRACT_PORTS(sctp, sctp);
SUBTRACT_PORTS(syn_ping, tcp);
SUBTRACT_PORTS(ack_ping, tcp);
SUBTRACT_PORTS(udp_ping, udp);
SUBTRACT_PORTS(sctp_ping, sctp);
#define prot_ports prots
SUBTRACT_PORTS(prot, prot);
SUBTRACT_PORTS(proto_ping, prot);
#undef prot_ports
#undef SUBTRACT_PORTS
free_scan_lists(&exclude_ports);
}
/* This function returns the number of ports that remain after the excluded ports
are removed from the ports. It places these ports at the start of the ports array. */
static int remaining_ports(unsigned short int *ports, int count, unsigned short int *exclude_ports, int exclude_count, const char *type) {
static bool has_been_excluded[65536];
int i, j;
if (count == 0 || exclude_count == 0)
return count;
if (o.debugging > 1)
log_write(LOG_STDOUT, "Removed %s ports: ", type);
for (i = 0; i < 65536; i++)
has_been_excluded[i] = false;
for (i = 0; i < exclude_count; i++)
has_been_excluded[exclude_ports[i]] = true;
for (i = 0, j = 0; i < count; i++)
if (!has_been_excluded[ports[i]])
ports[j++] = ports[i];
else if (o.debugging > 1)
log_write(LOG_STDOUT, "%d ", ports[i]);
if (o.debugging > 1) {
if (count-j) {
log_write(LOG_STDOUT, "\n");
} else {
log_write(LOG_STDOUT, "None\n");
}
}
if (o.debugging && count-j) {
log_write(LOG_STDOUT, "Removed %d %s ports that would have been considered for scanning otherwise.\n", count-j, type);
}
return j;
}
/* getpts() and getpts_simple() (see above) are wrappers for this function */
static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_type, int *portwarning, bool change_range_type) {
@@ -2548,10 +2647,10 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_
rangestart = strtol(current_range, &endptr, 10);
if (range_type & SCAN_PROTOCOLS) {
if (rangestart < 0 || rangestart > 255)
fatal("Protocols to be scanned must be between 0 and 255 inclusive");
fatal("Protocols specified must be between 0 and 255 inclusive");
} else {
if (rangestart < 0 || rangestart > 65535)
fatal("Ports to be scanned must be between 0 and 65535 inclusive");
fatal("Ports specified must be between 0 and 65535 inclusive");
}
current_range = endptr;
while (isspace((int) (unsigned char) *current_range)) current_range++;
@@ -2595,10 +2694,10 @@ static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_
rangeend = strtol(current_range, &endptr, 10);
if (range_type & SCAN_PROTOCOLS) {
if (rangeend < 0 || rangeend > 255)
fatal("Protocols to be scanned must be between 0 and 255 inclusive");
fatal("Protocols specified must be between 0 and 255 inclusive");
} else {
if (rangeend < 0 || rangeend > 65535)
fatal("Ports to be scanned must be between 0 and 65535 inclusive");
fatal("Ports specified must be between 0 and 65535 inclusive");
}
current_range = endptr;
} else {

1
nmap.h
View File

@@ -436,6 +436,7 @@ void printinteractiveusage();
void getpts(const char *expr, struct scan_lists * ports); /* someone stole the name getports()! */
void getpts_simple(const char *origexpr, int range_type,
unsigned short **list, int *count);
void removepts(const char *expr, struct scan_lists * ports);
void free_scan_lists(struct scan_lists *ports);
/* Renamed main so that interactive mode could preprocess when necessary */

View File

@@ -424,10 +424,13 @@ static bool is_port_member(const struct scan_lists *ptsdata, const struct servic
// If level is 1 or above, we treat it as a "top ports" directive
// and return the N highest ratio ports (where N==level).
//
// If the fourth parameter is not NULL, then the specified ports
// are excluded first and only then are the top N ports taken
//
// This function doesn't support IP protocol scan so only call this
// function if o.TCPScan() || o.UDPScan() || o.SCTPScan()
void gettoppts(double level, char *portlist, struct scan_lists * ports) {
void gettoppts(double level, char *portlist, struct scan_lists * ports, char *exclude_ports) {
int ti=0, ui=0, si=0;
struct scan_lists ptsdata = { 0 };
bool ptsdata_initialized = false;
@@ -466,7 +469,14 @@ void gettoppts(double level, char *portlist, struct scan_lists * ports) {
if (portlist){
getpts(portlist, &ptsdata);
ptsdata_initialized = true;
} else if (exclude_ports) {
getpts("-", &ptsdata);
ptsdata_initialized = true;
}
if (ptsdata_initialized && exclude_ports)
removepts(exclude_ports, &ptsdata);
if (level < 1) {
for (i = services_by_ratio.begin(); i != services_by_ratio.end(); i++) {
current = &(*i);

View File

@@ -150,7 +150,7 @@
int addportsfromservmask(char *mask, u8 *porttbl, int range_type);
struct servent *nmap_getservbyport(int port, const char *proto);
void gettoppts(double level, char *portlist, struct scan_lists * ports);
void gettoppts(double level, char *portlist, struct scan_lists * ports, char *exclude_list = NULL);
void free_services();

View File

@@ -1,5 +1,8 @@
DONE:
o Implement an --exclude-ports option. See
http://seclists.org/nmap-dev/2012/q1/275
o In an ideal world, Zenmap would not run out of memory and crash.
And we already have an entry for improving Zenmap's memory
consumption. But in the meantime, we should catch the error and

View File

@@ -58,8 +58,6 @@ o GSOC 2014 student Jay will be looking at these items:
o Consider using a binary decision diagram for --exclude list to make
it more efficient for large exclude lists. See
http://seclists.org/nmap-dev/2012/q4/420.
o Implement an --exclude-ports option. See
http://seclists.org/nmap-dev/2012/q1/275
o [Zenmap] Combine parallel timed-out hops into one node in the
topology view. http://seclists.org/nmap-dev/2012/q1/82 has a patch,
however it doesn't handle the case of two or more consecutive