This JFDI article will focus on creating your own port/banner scanner. This is something I had wanted to do for a long time, but never had a true motivator to spark (force) my interests.
The Origin of Bac0n
Back in November I was faced with a common situation that happens in the tech industry, an undocumented network. The lack of documentation was not intentional, it was just one of the many todo items on that looonnggg list (yeah, you know the one) for a former colleague to finish. Unfortunatley, he never got to it: too much todo, short timers disease, oversight, did I forget to write down the addresses when he told me, who knows. I had been slowly documenting the network, beyond the standard docs we already had (its those little details that matter the most). We had multiple Vmware servers running, spread out accross a multi-layered network that was number 198 on the list of things to fix. I knew the addresses of two servers, the others were anyones guess, no biggie NMAP to the rescue, right?
Wrong, wrong, wrong, for what ever reason NMAP could not find the servers, was it user error, or the overly complicated network, possibly? But the kicker is as in most pinch situations, I needed to know this yesterday; why, because the mail server went tango uniform. So, NMAP is not working, the two known IP address for the other servers do not follow a contiguous or logical order (guestimation is no longer an option). Bring on the bac0n.
Design of Bac0n
Bac0n is a very simple and straight forward design. It is designed to do the following tasks:
- Enumerate through the IP addresses of the specified netblock.
- Connect to each IP on the specified port.
- Read the banner on that port (if online).
- If the host is running Vmware, print the address.
What Makes Bac0n Sizzle
Bac0n in its current configuration only enumerates class C networks. The port and network range are obtained interactively from the command line.
netRange = raw_input("Net Range: ")
port = raw_input("Port: ")
This next section of code generates the list of IP addresses for the network and stores them in a dictionary (hash table) with a status of "no" indicating Vmware is not running on the host.
hostList = {}
for x in range(255):
if x == "0":
pass
else:
host = netRange + "." + str(x)
hostList[host] = "no"
This section of code enumerates through the hosts and attempts to make a complete TCP connection on the host and port. A timeout is set to .5 seconds to help expedite the processing, if not it can take up to 60 seconds for each host.
for host,status in hostList.items():
try:
socketConnector = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socketConnector.settimeout(.5)
socketConnector.connect((host,int(port)))
except:
pass
continue
This section reads the banner information and checks for VMware, if the host checks out, the status in the dictionary is updated.
banner = socketConnector.recv(8192)
socketConnector.close()
if "VMware" in banner:
hostList[host] = "yes"
The final section of code enumerates through the dictionary and prints all of the found hosts.
for host,status in hostList.items():
if status == "yes":
print host
Taking Things Further
There are many options available from here, we can add other networks, ports, protocols etc. The script can adapted to read from file, the possibilities are endless. Bac0n found all the servers, and I was able to bring the mail server back online.