Building a pocket nmap-like tool out of nothing

January 22, 2014 | 4 Minute Read

As I said in another post, I like to leave computers in every sort of place I can call home, in order to connect to them in case in need something. Also, I left a small, third hand, screenless laptop at home in Lecce, connected to the Internet, waiting for connections.

Today I logged in, and used ssh to connect to other hosts and perform updates.

But I couldn’t recall what other hosts’ ip addresses were.

In this cases, I use nmap’s ping scan to determine (with a certain accuracy) what hosts are available on the network (and other things…).

Nmap was not installed on that host and being a crappy computer with a slow network and a slow hard drive, installing it was taking ages, and I didn’t feel like waiting.

What I realized is that I can perform almost the same task without nmap.

What does nmap do when performing ping-scan? Basically it’s going to send an icmp echo request (a.k.a “ping”) to all the hosts in the given network, and print back results.

That’s basically what ping(8) does.

Since that host is in a typical c-class /24 network, a simple nmap-like tool (for the purpose) can be coded this way:

for i in `seq 1 1 254`; do ping -c1 192.16x.1.$i; done

Output will be shown in the terminal, and of course can be paged using some sort of pager like less or more (my favorite pager is most).

Of course, it will print a lot of unuseful output  (for example: “host unreachable” message when a host is unreachable) and a simple way to filter out good output would be grepping for strings like “64 bytes”, as in “64 bytes from icmp_req=1 ttl=64 time=8.62 ms” (a typical message of success ping).

So a better version would be:

for i in `seq 1 1 254`; do ping -c1 192.16x.1.$i; done | grep “64 bytes”

Way better as one-liner, still not perfect.

This is how far I went in those five minutes, but this thing can be easily taken further: a proper way to do this would be simply executing ping(8) and confronting its exit code with a known success exit code.

Ubuntu 12.04 LTS’ man page for ping(8) doesn’t list exit codes, but from trivial experiments it seems that exit code is 0 for success ping and 1 for packet loss (this comes from pinging an existing host and a non-existing host and looking at their return codes in $?). I would prefer something official, but ping(8) manpage doesn’t list anything and it’s too late to dig its source code (something that would surely be interesting to do).

Also, the whole thing could be sped up by running multiple instances of ping(8) in parallel or by lowering its timeout time via the -W option.

Why does this matter? First of all it seems to me a nice hack. Also, it could be very useful when no sort of port scanner is available (protip: you’ve hacked into a remote router, and would like to know what hosts are available on the network or on networks connected to the network but not on the same collision domain. What do you do? nmap isn’t available, but ping is typically available for testing/diagnostic purposes).

Just a little idea I wanted to share.