From: Guilhem Moulin Date: Mon, 22 Oct 2018 04:15:52 +0200 Subject: destination port list --- nc.1 | 26 ++++++++++++++++--- netcat.c | 86 ++++++++++++++++++++++++++++++++------------------------------- 2 files changed, 68 insertions(+), 44 deletions(-) --- a/nc.1 +++ b/nc.1 @@ -414,15 +414,35 @@ The flag can be used to tell .Nm to report open ports, -rather than initiate a connection. +rather than initiate a connection. Usually it's useful to turn on verbose +output to stderr by use this option in conjunction with +.Fl v +option. +.Pp For example: .Bd -literal -offset indent -$ nc -z host.example.com 20-30 +$ nc \-zv host.example.com 20-30 Connection to host.example.com 22 port [tcp/ssh] succeeded! Connection to host.example.com 25 port [tcp/smtp] succeeded! .Ed .Pp -The port range was specified to limit the search to ports 20 \- 30. +The port range was specified to limit the search to ports 20 \- 30, and is +scanned by increasing order (unless the +.Fl r +flag is set). +.Pp +You can also specify a list of ports to scan, for example: +.Bd -literal -offset indent +$ nc \-zv host.example.com http 20 22-23 +nc: connect to host.example.com 80 (tcp) failed: Connection refused +nc: connect to host.example.com 20 (tcp) failed: Connection refused +Connection to host.example.com port [tcp/ssh] succeeded! +nc: connect to host.example.com 23 (tcp) failed: Connection refused +.Ed +.Pp +The ports are scanned by the order you given (unless the +.Fl r +flag is set). .Pp Alternatively, it might be useful to know which server software is running, and which versions. --- a/netcat.c +++ b/netcat.c @@ -191,7 +191,7 @@ int minttl = -1; void atelnet(int, unsigned char *, unsigned int); int strtoport(char *portstr, int udp); -void build_ports(char *); +void build_ports(char **); void help(void) __attribute__((noreturn)); int local_listen(const char *, const char *, struct addrinfo); # if defined(TLS) @@ -242,7 +242,7 @@ int main(int argc, char *argv[]) { int ch, s = -1, ret, socksv; - char *host, *uport; + char *host, **uport; struct addrinfo hints; struct servent *sv; socklen_t len; @@ -526,11 +526,11 @@ main(int argc, char *argv[]) } else if (argv[0] && !argv[1]) { if (!lflag) usage(1); - uport = argv[0]; + uport = &argv[0]; host = NULL; } else if (argv[0] && argv[1]) { host = argv[0]; - uport = argv[1]; + uport = &argv[1]; } else usage(1); @@ -717,7 +717,7 @@ main(int argc, char *argv[]) else s = unix_listen(host); } else - s = local_listen(host, uport, hints); + s = local_listen(host, *uport, hints); if (s < 0) err(1, NULL); @@ -1785,57 +1785,61 @@ strtoport(char *portstr, int udp) * that we should try to connect to. */ void -build_ports(char *p) +build_ports(char **p) { struct servent *sv; char *n; int hi, lo, cp; int x = 0; + int i; char *proto = proto_name(uflag, dccpflag); - sv = getservbyname(p, proto); - if (sv) { - if (asprintf(&portlist[0], "%d", ntohs(sv->s_port)) < 0) - err(1, "asprintf"); - } else if (isdigit((unsigned char)*p) && (n = strchr(p, '-')) != NULL) { - *n = '\0'; - n++; - - /* Make sure the ports are in order: lowest->highest. */ - hi = strtoport(n, uflag); - lo = strtoport(p, uflag); - if (lo > hi) { - cp = hi; - hi = lo; - lo = cp; - } - - /* - * Initialize portlist with a random permutation. Based on - * Knuth, as in ip_randomid() in sys/netinet/ip_id.c. - */ - if (rflag) { - for (x = 0; x <= hi - lo; x++) { - cp = arc4random_uniform(x + 1); - portlist[x] = portlist[cp]; - if (asprintf(&portlist[cp], "%d", x + lo) < 0) - err(1, "asprintf"); + for (i = 0; p[i] != NULL; i++) { + sv = getservbyname(p[i], proto); + if (sv) { + if (asprintf(&portlist[x], "%d", ntohs(sv->s_port)) < 0) + err(1, "asprintf"); + x++; + } else if (isdigit((unsigned char)*p[i]) && (n = strchr(p[i], '-')) != NULL) { + *n = '\0'; + n++; + + /* Make sure the ports are in order: lowest->highest. */ + hi = strtoport(n, uflag); + lo = strtoport(p[i], uflag); + if (lo > hi) { + cp = hi; + hi = lo; + lo = cp; } - } else { /* Load ports sequentially. */ + + /* Load ports sequentially. */ for (cp = lo; cp <= hi; cp++) { if (asprintf(&portlist[x], "%d", cp) < 0) err(1, "asprintf"); x++; } + } else { + hi = strtoport(p[i], uflag); + if (asprintf(&portlist[x], "%d", hi) < 0) + err(1, "asprintf"); + x++; } - } else { - char *tmp; + } - hi = strtoport(p, uflag); - if (asprintf(&tmp, "%d", hi) != -1) - portlist[0] = tmp; - else - err(1, NULL); + /* + * Initialize portlist with a random permutation using + * Fisher–Yates shuffle. + */ + if (rflag) { + for (i = x-1; i > 0; i--) { + cp = arc4random_uniform(i+1); + if (cp != i) { + n = portlist[i]; + portlist[i] = portlist[cp]; + portlist[cp] = n; + } + } } }