1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-10 17:59:04 +00:00

Remove the artificial cap on the number of ping scan ports and protocols. Port

lists for ping scan now use the same syntax as the -p option except that T:,
U:, and P: are not allowed.
This commit is contained in:
david
2007-11-01 16:15:11 +00:00
parent 9dfd8af1f3
commit 2e65b35f84
7 changed files with 157 additions and 84 deletions

View File

@@ -5,6 +5,14 @@ o Removed the NmapFE frontend.
o Updated IANA assignment IP list for random IP (-iR) o Updated IANA assignment IP list for random IP (-iR)
generation. [Kris] generation. [Kris]
o There is no longer any artificial limit on the number of ports or
protocols that can be used for host discovery. Port lists for ping
scan now use the same syntax as the -p option except that T:, U:,
and P: are not allowed. This means that you can do
nmap -PS1-1000 target
nmap -PAhttp,https target
nmap -PU'[-]' target
4.22SOC8 4.22SOC8
o Removed the old massping() system, since the functionality has now o Removed the old massping() system, since the functionality has now

View File

@@ -101,6 +101,7 @@
#include "nmap.h" #include "nmap.h"
#include "nbase.h" #include "nbase.h"
#include "NmapOps.h" #include "NmapOps.h"
#include "services.h"
#include "utils.h" #include "utils.h"
#ifdef WIN32 #ifdef WIN32
#include "winfix.h" #include "winfix.h"
@@ -115,6 +116,10 @@ NmapOps::NmapOps() {
} }
NmapOps::~NmapOps() { NmapOps::~NmapOps() {
if (ping_synprobes) free(ping_synprobes);
if (ping_ackprobes) free(ping_ackprobes);
if (ping_udpprobes) free(ping_udpprobes);
if (ping_protoprobes) free(ping_protoprobes);
if (datadir) free(datadir); if (datadir) free(datadir);
if (xsl_stylesheet) free(xsl_stylesheet); if (xsl_stylesheet) free(xsl_stylesheet);
} }
@@ -203,6 +208,7 @@ void NmapOps::Initialize() {
magic_port = 33000 + (get_random_uint() % 31000); magic_port = 33000 + (get_random_uint() % 31000);
magic_port_set = 0; magic_port_set = 0;
num_ping_synprobes = num_ping_ackprobes = num_ping_udpprobes = num_ping_protoprobes = 0; num_ping_synprobes = num_ping_ackprobes = num_ping_udpprobes = num_ping_protoprobes = 0;
ping_synprobes = ping_ackprobes = ping_udpprobes = ping_protoprobes = NULL;
timing_level = 3; timing_level = 3;
max_parallelism = 0; max_parallelism = 0;
min_parallelism = 0; min_parallelism = 0;
@@ -304,8 +310,8 @@ void NmapOps::ValidateOptions() {
if (pingtype == PINGTYPE_UNKNOWN) { if (pingtype == PINGTYPE_UNKNOWN) {
if (isr00t && af() == AF_INET) pingtype = DEFAULT_PING_TYPES; if (isr00t && af() == AF_INET) pingtype = DEFAULT_PING_TYPES;
else pingtype = PINGTYPE_TCP; // if nonr00t or IPv6 else pingtype = PINGTYPE_TCP; // if nonr00t or IPv6
num_ping_ackprobes = 1; getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &o.ping_ackprobes, &o.num_ping_ackprobes);
ping_ackprobes[0] = DEFAULT_TCP_PROBE_PORT; assert(o.num_ping_ackprobes > 0);
} }
/* Insure that at least one scantype is selected */ /* Insure that at least one scantype is selected */
@@ -322,10 +328,12 @@ void NmapOps::ValidateOptions() {
fatal("Cannot use both SYN and ACK ping probes if you are nonroot or using IPv6"); fatal("Cannot use both SYN and ACK ping probes if you are nonroot or using IPv6");
} }
/* Pretend we wanted SYN probes all along. */
if (num_ping_ackprobes > 0) { if (num_ping_ackprobes > 0) {
memcpy(ping_synprobes, ping_ackprobes, num_ping_ackprobes * sizeof(*ping_synprobes));
num_ping_synprobes = num_ping_ackprobes; num_ping_synprobes = num_ping_ackprobes;
ping_synprobes = ping_ackprobes;
num_ping_ackprobes = 0; num_ping_ackprobes = 0;
ping_ackprobes = NULL;
} }
pingtype &= ~PINGTYPE_TCP_USE_ACK; pingtype &= ~PINGTYPE_TCP_USE_ACK;
pingtype |= PINGTYPE_TCP_USE_SYN; pingtype |= PINGTYPE_TCP_USE_SYN;
@@ -384,8 +392,8 @@ void NmapOps::ValidateOptions() {
pingtype = PINGTYPE_TCP; pingtype = PINGTYPE_TCP;
if (num_ping_synprobes == 0) if (num_ping_synprobes == 0)
{ {
num_ping_synprobes = 1; getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &o.ping_synprobes, &o.num_ping_synprobes);
ping_synprobes[0] = DEFAULT_TCP_PROBE_PORT; assert(o.num_ping_synprobes > 0);
} }
} }
#endif #endif

View File

@@ -191,13 +191,13 @@ class NmapOps {
unsigned short magic_port_set; /* Was this set by user? */ unsigned short magic_port_set; /* Was this set by user? */
int num_ping_synprobes; int num_ping_synprobes;
/* The "synprobes" are also used when doing a connect() ping */ /* The "synprobes" are also used when doing a connect() ping */
u16 ping_synprobes[MAX_PROBE_PORTS]; u16 *ping_synprobes;
int num_ping_ackprobes; int num_ping_ackprobes;
u16 ping_ackprobes[MAX_PROBE_PORTS]; u16 *ping_ackprobes;
int num_ping_udpprobes; int num_ping_udpprobes;
u16 ping_udpprobes[MAX_PROBE_PORTS]; u16 *ping_udpprobes;
int num_ping_protoprobes; int num_ping_protoprobes;
u16 ping_protoprobes[MAX_PROBE_PORTS]; u16 *ping_protoprobes;
/* Scan timing/politeness issues */ /* Scan timing/politeness issues */
int timing_level; // 0-5, corresponding to Paranoid, Sneaky, Polite, Normal, Aggressive, Insane int timing_level; // 0-5, corresponding to Paranoid, Sneaky, Polite, Normal, Aggressive, Insane
int max_parallelism; // 0 means it has not been set int max_parallelism; // 0 means it has not been set

View File

@@ -449,12 +449,15 @@ you would expect.</para>
<para>This option sends an empty TCP packet with the SYN <para>This option sends an empty TCP packet with the SYN
flag set. The default destination port is 80 (configurable flag set. The default destination port is 80 (configurable
at compile time by changing DEFAULT_TCP_PROBE_PORT in at compile time by changing DEFAULT_TCP_PROBE_PORT_SPEC in
<filename>nmap.h</filename>), but an alternate port can be <filename>nmap.h</filename>). Alternate ports can be
specified as a parameter. A comma separated list of ports specified as a parameter. The syntax is the same as for the
can even be specified <option>-p</option> except that port type specifiers like
(e.g. <option>-PS22,23,25,80,113,1050,35000</option>), in <literal>T:</literal> are not allowed. Examples are
which case probes will be attempted against each port in <option>-PS22</option> and
<option>-PS22-25,80,113,1050,35000</option>. Note that there
can be no space between <option>-PS</option> and the port
list. If multiple probes are specified they will be sent in
parallel.</para> parallel.</para>
<para>The SYN flag suggests to the remote system that you <para>The SYN flag suggests to the remote system that you
@@ -563,8 +566,8 @@ you would expect.</para>
<option>-PS</option> and <option>-PA</option> options. If <option>-PS</option> and <option>-PA</option> options. If
no ports are specified, the default is 31338. This default no ports are specified, the default is 31338. This default
can be configured at compile-time by changing can be configured at compile-time by changing
DEFAULT_UDP_PROBE_PORT in <filename>nmap.h</filename>. A DEFAULT_UDP_PROBE_PORT_SPEC in <filename>nmap.h</filename>.
highly uncommon port is used by default because sending to A highly uncommon port is used by default because sending to
open ports is often undesirable for this particular scan open ports is often undesirable for this particular scan
type.</para> type.</para>
@@ -659,11 +662,12 @@ you would expect.</para>
no protocols are specified, the default is to send multiple no protocols are specified, the default is to send multiple
IP packets for ICMP (protocol 1), IGMP (protocol 2), and IP packets for ICMP (protocol 1), IGMP (protocol 2), and
IP-in-IP (protocol 4). The default protocols can be IP-in-IP (protocol 4). The default protocols can be
configured at compile-time by changing DEFAULT_PROTO_PROBE_PORTS configured at compile-time by changing
in <filename>nmap.h</filename>. Note that for the ICMP, IGMP, DEFAULT_PROTO_PROBE_PORT_SPEC in <filename>nmap.h</filename>.
TCP (protocol 6), and UDP (protocol 17), the packets are sent Note that for the ICMP, IGMP, TCP (protocol 6), and UDP
with the additional headers while other protocols are sent with (protocol 17), the packets are sent with the additional
no additional data beyond the IP header (unless the headers while other protocols are sent with no additional data
beyond the IP header (unless the
<option>--data-length</option> option is specified).</para> <option>--data-length</option> option is specified).</para>
<para>This host discovery method looks for responses in the <para>This host discovery method looks for responses in the

View File

@@ -108,6 +108,7 @@
#include "osscan.h" #include "osscan.h"
#include "nmap.h" #include "nmap.h"
#include "NmapOps.h" #include "NmapOps.h"
#include "services.h"
#include "Target.h" #include "Target.h"
#include "utils.h" #include "utils.h"
@@ -330,9 +331,19 @@ static void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName,
fatal("Invalid port number given in IP ID zombie specification: %s", proxyName); fatal("Invalid port number given in IP ID zombie specification: %s", proxyName);
} }
} else { } else {
proxy->probe_port = (o.num_ping_synprobes > 0)? o.ping_synprobes[0] : if (o.num_ping_synprobes > 0) {
(o.num_ping_ackprobes > 0)? o.ping_ackprobes[0] : proxy->probe_port = o.ping_synprobes[0];
DEFAULT_TCP_PROBE_PORT; } else if (o.num_ping_ackprobes > 0) {
proxy->probe_port = o.ping_ackprobes[0];
} else {
u16 *ports;
int count;
getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &ports, &count);
assert(count > 0);
proxy->probe_port = ports[0];
free(ports);
}
} }
proxy->host.setHostName(name); proxy->host.setHostName(name);

143
nmap.cc
View File

@@ -492,7 +492,6 @@ int nmap_main(int argc, char *argv[]) {
Target *currenths; Target *currenths;
vector<Target *> Targets; vector<Target *> Targets;
char *portlist = NULL; /* Ports list specified by user */ char *portlist = NULL; /* Ports list specified by user */
char *proberr;
int sourceaddrwarning = 0; /* Have we warned them yet about unguessable int sourceaddrwarning = 0; /* Have we warned them yet about unguessable
source addresses? */ source addresses? */
unsigned int ideal_scan_group_sz = 0; unsigned int ideal_scan_group_sz = 0;
@@ -1029,70 +1028,68 @@ int nmap_main(int argc, char *argv[]) {
o.pingtype |= PINGTYPE_ARP; o.pingtype |= PINGTYPE_ARP;
else if (*optarg == 'S') { else if (*optarg == 'S') {
o.pingtype |= (PINGTYPE_TCP|PINGTYPE_TCP_USE_SYN); o.pingtype |= (PINGTYPE_TCP|PINGTYPE_TCP_USE_SYN);
if (isdigit((int) *(optarg+1))) if (*(optarg + 1) != '\0') {
{ getpts_simple(optarg + 1, SCAN_TCP_PORT, &o.ping_synprobes, &o.num_ping_synprobes);
o.num_ping_synprobes = numberlist2array(optarg+1, o.ping_synprobes, sizeof(o.ping_synprobes), &proberr); if (o.num_ping_synprobes <= 0) {
if (o.num_ping_synprobes < 0) { fatal("Bogus argument to -PS: %s", optarg + 1);
fatal("Bogus argument to -PS: %s", proberr);
}
} }
}
if (o.num_ping_synprobes == 0) { if (o.num_ping_synprobes == 0) {
o.num_ping_synprobes = 1; getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &o.ping_synprobes, &o.num_ping_synprobes);
o.ping_synprobes[0] = DEFAULT_TCP_PROBE_PORT; assert(o.num_ping_synprobes > 0);
} }
} }
else if (*optarg == 'T' || *optarg == 'A') { else if (*optarg == 'T' || *optarg == 'A') {
/* NmapOps::ValidateOptions() takes care of changing this /* NmapOps::ValidateOptions() takes care of changing this
to SYN if not root or if IPv6 */ to SYN if not root or if IPv6 */
o.pingtype |= (PINGTYPE_TCP|PINGTYPE_TCP_USE_ACK); o.pingtype |= (PINGTYPE_TCP|PINGTYPE_TCP_USE_ACK);
if (isdigit((int) *(optarg+1))) { if (*(optarg + 1) != '\0') {
o.num_ping_ackprobes = numberlist2array(optarg+1, o.ping_ackprobes, sizeof(o.ping_ackprobes), &proberr); getpts_simple(optarg + 1, SCAN_TCP_PORT, &o.ping_ackprobes, &o.num_ping_ackprobes);
if (o.num_ping_ackprobes < 0) { if (o.num_ping_ackprobes <= 0) {
fatal("Bogus argument to -PA: %s", proberr); fatal("Bogus argument to -PA: %s", optarg + 1);
} }
} }
if (o.num_ping_ackprobes == 0) { if (o.num_ping_ackprobes == 0) {
o.num_ping_ackprobes = 1; getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &o.ping_ackprobes, &o.num_ping_ackprobes);
o.ping_ackprobes[0] = DEFAULT_TCP_PROBE_PORT; assert(o.num_ping_ackprobes > 0);
} }
} }
else if (*optarg == 'U') { else if (*optarg == 'U') {
o.pingtype |= (PINGTYPE_UDP); o.pingtype |= (PINGTYPE_UDP);
if (isdigit((int) *(optarg+1))) { if (*(optarg + 1) != '\0') {
o.num_ping_udpprobes = numberlist2array(optarg+1, o.ping_udpprobes, sizeof(o.ping_udpprobes), &proberr); getpts_simple(optarg + 1, SCAN_UDP_PORT, &o.ping_udpprobes, &o.num_ping_udpprobes);
if (o.num_ping_udpprobes < 0) { if (o.num_ping_udpprobes <= 0) {
fatal("Bogus argument to -PU: %s", proberr); fatal("Bogus argument to -PU: %s", optarg + 1);
} }
} }
if (o.num_ping_udpprobes == 0) { if (o.num_ping_udpprobes == 0) {
o.num_ping_udpprobes = 1; getpts_simple(DEFAULT_UDP_PROBE_PORT_SPEC, SCAN_UDP_PORT, &o.ping_udpprobes, &o.num_ping_udpprobes);
o.ping_udpprobes[0] = DEFAULT_UDP_PROBE_PORT; assert(o.num_ping_udpprobes > 0);
} }
} }
else if (*optarg == 'B') { else if (*optarg == 'B') {
o.pingtype = (PINGTYPE_TCP|PINGTYPE_TCP_USE_ACK|PINGTYPE_ICMP_PING); o.pingtype = (PINGTYPE_TCP|PINGTYPE_TCP_USE_ACK|PINGTYPE_ICMP_PING);
if (isdigit((int) *(optarg+1))) { if (*(optarg + 1) != '\0') {
o.num_ping_ackprobes = numberlist2array(optarg+1, o.ping_ackprobes, sizeof(o.ping_ackprobes), &proberr); getpts_simple(optarg + 1, SCAN_TCP_PORT, &o.ping_ackprobes, &o.num_ping_ackprobes);
if (o.num_ping_ackprobes < 0) { if (o.num_ping_ackprobes <= 0) {
fatal("Bogus argument to -PB: %s", proberr); fatal("Bogus argument to -PB: %s", optarg + 1);
} }
} }
if (o.num_ping_ackprobes == 0) { if (o.num_ping_ackprobes == 0) {
o.num_ping_ackprobes = 1; getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &o.ping_ackprobes, &o.num_ping_ackprobes);
o.ping_ackprobes[0] = DEFAULT_TCP_PROBE_PORT; assert(o.num_ping_ackprobes > 0);
} }
} else if (*optarg == 'O') { } else if (*optarg == 'O') {
o.pingtype |= PINGTYPE_PROTO; o.pingtype |= PINGTYPE_PROTO;
if (isdigit((int) *(optarg+1))) { if (*(optarg + 1) != '\0') {
o.num_ping_protoprobes = numberlist2array(optarg+1, o.ping_protoprobes, sizeof(o.ping_protoprobes), &proberr, 0, 255); getpts_simple(optarg + 1, SCAN_PROTOCOLS, &o.ping_protoprobes, &o.num_ping_protoprobes);
if (o.num_ping_protoprobes < 0) { if (o.num_ping_protoprobes <= 0) {
fatal("Bogus argument to -PO: %s", proberr); fatal("Bogus argument to -PO: %s", optarg + 1);
} }
} }
if (o.num_ping_protoprobes == 0) { if (o.num_ping_protoprobes == 0) {
u16 probes[] = DEFAULT_PROTO_PROBE_PORTS; getpts_simple(DEFAULT_PROTO_PROBE_PORT_SPEC, SCAN_PROTOCOLS, &o.ping_protoprobes, &o.num_ping_protoprobes);
o.num_ping_protoprobes = sizeof probes / sizeof *probes; assert(o.num_ping_protoprobes > 0);
memcpy(o.ping_protoprobes, probes, sizeof probes);
} }
} else { } else {
fatal("Illegal Argument to -P, use -PN, -PO, -PI, -PB, -PE, -PM, -PP, -PA, -PU, -PT, or -PT80 (or whatever number you want for the TCP probe destination port)"); fatal("Illegal Argument to -P, use -PN, -PO, -PI, -PB, -PE, -PM, -PP, -PA, -PU, -PT, or -PT80 (or whatever number you want for the TCP probe destination port)");
@@ -2059,8 +2056,8 @@ void init_socket(int sd) {
* the outer part of the port expression. It's "closed". * the outer part of the port expression. It's "closed".
*/ */
static void getpts_aux(char *origexpr, int nested, u8 *porttbl, int range_type, int static void getpts_aux(char *origexpr, int nested, u8 *porttbl, int range_type,
*portwarning); int *portwarning, bool change_range_type = true);
struct scan_lists *getpts(char *origexpr) { struct scan_lists *getpts(char *origexpr) {
u8 *porttbl; u8 *porttbl;
@@ -2125,10 +2122,49 @@ struct scan_lists *getpts(char *origexpr) {
} }
/* This function is like getpts except that instead of returning several lists
of ports in a struct scan_lists, it allocates only one list and stores it in
the list and count arguments. For that reason, T:, U:, and P: restrictions
are not allowed and only one bit in range_type may be set. */
void getpts_simple(char *origexpr, int range_type,
unsigned short **list, int *count) {
u8 *porttbl;
int portwarning = 0;
int i, j;
/* getpts() (see above) is a wrapper for this function */ /* Make sure that only one bit in range_type is set (or that range_type is 0,
which is useless but not incorrect). */
assert((range_type & (range_type - 1)) == 0);
static void getpts_aux(char *origexpr, int nested, u8 *porttbl, int range_type, int *portwarning) { porttbl = (u8 *) safe_zalloc(65536);
/* Get the ports but do not allow changing the type with T:, U:, or P:. */
getpts_aux(origexpr, 0, porttbl, range_type, &portwarning, false);
/* Count how many are set. */
*count = 0;
for (i = 0; i <= 65535; i++) {
if (porttbl[i] & range_type)
(*count)++;
}
if (*count == 0)
return;
*list = (unsigned short *) safe_zalloc(*count * sizeof(unsigned short));
/* Fill in the list. */
for (i = 0, j = 0; i <= 65535; i++) {
if (porttbl[i] & range_type)
(*list)[j++] = i;
}
free(porttbl);
}
/* getpts() and getpts_simple() (see above) are wrappers for this function */
static void getpts_aux(char *origexpr, int nested, u8 *porttbl, int range_type, int *portwarning, bool change_range_type) {
long rangestart = -2343242, rangeend = -9324423; long rangestart = -2343242, rangeend = -9324423;
char *current_range; char *current_range;
char *endptr; char *endptr;
@@ -2140,21 +2176,24 @@ static void getpts_aux(char *origexpr, int nested, u8 *porttbl, int range_type,
while(isspace((int) *current_range)) while(isspace((int) *current_range))
current_range++; /* I don't know why I should allow spaces here, but I will */ current_range++; /* I don't know why I should allow spaces here, but I will */
if (*current_range == 'T' && *++current_range == ':') { if (change_range_type) {
current_range++; if (*current_range == 'T' && *++current_range == ':') {
range_type = SCAN_TCP_PORT; current_range++;
continue; range_type = SCAN_TCP_PORT;
} continue;
if (*current_range == 'U' && *++current_range == ':') { }
current_range++; if (*current_range == 'U' && *++current_range == ':') {
range_type = SCAN_UDP_PORT; current_range++;
continue; range_type = SCAN_UDP_PORT;
} continue;
if (*current_range == 'P' && *++current_range == ':') { }
current_range++; if (*current_range == 'P' && *++current_range == ':') {
range_type = SCAN_PROTOCOLS; current_range++;
continue; range_type = SCAN_PROTOCOLS;
continue;
}
} }
if (*current_range == '[') { if (*current_range == '[') {
if (nested) if (nested)
fatal("Can't nest [] brackets in -p switch"); fatal("Can't nest [] brackets in -p switch");

17
nmap.h
View File

@@ -272,13 +272,14 @@ void *realloc();
#define MAX_TIMEOUTS MAX_SOCKETS /* How many timed out connection attempts #define MAX_TIMEOUTS MAX_SOCKETS /* How many timed out connection attempts
in a row before we decide the host is in a row before we decide the host is
dead? */ dead? */
#define DEFAULT_TCP_PROBE_PORT 80 /* The port TCP probes go to if unspecified #define DEFAULT_TCP_PROBE_PORT_SPEC "80" /* The ports TCP probes go to if
by user -- uber hackers change this unspecified by user -- uber hackers
to 113 */ change this to 113 */
#define DEFAULT_UDP_PROBE_PORT 31338 /* The port UDP probes (esp. "ping" probes) go to if unspecified #define DEFAULT_UDP_PROBE_PORT_SPEC "31338" /* The port UDP probes (esp. "ping"
by user */ probes) go to if unspecified by
#define DEFAULT_PROTO_PROBE_PORTS { 1, 2, 4 } /* The IPProto ping probes to use if unspecified user */
by user */ #define DEFAULT_PROTO_PROBE_PORT_SPEC "1,2,4" /* The IPProto ping probes to use
if unspecified by user */
#define MAX_DECOYS 128 /* How many decoys are allowed? */ #define MAX_DECOYS 128 /* How many decoys are allowed? */
@@ -412,6 +413,8 @@ int ftp_anon_connect(struct ftpinfo *ftp);
/* port manipulators */ /* port manipulators */
struct scan_lists *getpts(char *expr); /* someone stole the name getports()! */ struct scan_lists *getpts(char *expr); /* someone stole the name getports()! */
void getpts_simple(char *origexpr, int range_type,
unsigned short **list, int *count);
void free_scan_lists(struct scan_lists *ports); void free_scan_lists(struct scan_lists *ports);
/* socket manipulation functions */ /* socket manipulation functions */