My Network Setup
My Machine: Ubuntu 14.04 LTS with Python 2.7.6, IP address: 192.168.209.128
Another Machine: “Damn Vulnerable Linux” (DVL), IP address: 192.168.209.129
Port Scanning
import optparse
from socket import *
def conn(targetHost, targetPort):
try:
conn = socket(AF_INET, SOCK_STREAM)
conn.connect((targetHost, targetPort))
print '[+] Connection to ' + targetHost + ' port ' + str(targetPort) + ' succeeded!'
except Exception, e:
print '[-] Connection to ' + targetHost + ' port ' + str(targetPort) + ' failed: ' + str(e)
finally:
conn.close()
def main():
parser = optparse.OptionParser("%prog -t <target host(s)> -p <target port(s)>")
parser.add_option('-t', dest='targetHosts', type='string', help='Specify the target host(s); Separate them by commas')
parser.add_option('-p', dest='targetPorts', type='string', help='Specify the target port(s); Separate them by commas')
(options, args) = parser.parse_args()
if (options.targetHosts == None) | (options.targetPorts == None):
print parser.usage
exit(0)
targetHosts = str(options.targetHosts).split(',')
targetPorts = str(options.targetPorts).split(',')
setdefaulttimeout(5)
for targetHost in targetHosts:
for targetPort in targetPorts:
conn(targetHost, int(targetPort))
print ''
if __name__ == '__main__':
main()
Taking in 2 arguments (-t for target hosts/nodes, and -p for target ports), it informs the user if the port is open or close by attempting to create a socket connection to the respective host-port combination. The port is considered as open if the attempt succeeds, and close otherwise.
An example of my script’s output:
python PortScanner .py –t 192.168.98.128,192.168.98.129,edgis –p 21,22,80,3306
My Ubuntu machine has SSH and Apache2 service running. And my DVL has an additional MySQL service running. Host “edgis” does not exist on my network.
Port Scanning using Python-Nmap Library
My Python script allows user to scan multiple hosts and ports by listing them (separated by commas). But what about notations such as a range of hosts/ports (using the character ‘-‘) like what Nmap allows? We can certainly expand the existing script to fit such needs, but why rebuild the wheel Nmap has provided? Here’s how you can utilise the Python-Nmap library.
import optparse
import nmap
def nmapScan(targetHosts, targetPorts):
try:
scanner = nmap.PortScanner()
scanner.scan(targetHosts, targetPorts)
for targetHost in scanner.all_hosts():
if scanner[targetHost].state() == 'up':
print targetHost + ' is up'
for targetPort in scanner[targetHost]['tcp']:
print 'Port ' + str(targetPort) + '/tcp ' + scanner[targetHost]['tcp'][int(targetPort)]['name'] + ' is ' + scanner[targetHost]['tcp'][int(targetPort)]['state']
print ''
except Exception, e:
print '[-] Something bad happened during the scan: ' + str(e)
def main():
...
targetHosts = str(options.targetHosts)
targetPorts = str(options.targetPorts)
nmapScan(targetHosts, targetPorts)
python NmapScanner.py -t 192.168.98.125-130 -p 20,21,80,3306
python NmapScanner.py –t 192.168.98.125-130 –p 1-1024
Banner Grabbing
Port scanning identifies a list of open ports of a target host. Sometimes it’s necessary to find out more about the services running on these ports. Banner grabbing is one of the easiest methods to do so.
This can be easily done by adding an additional function grab(), and editing the existing conn() function to the first script mentioned above.
def conn(targetHost, targetPort):
try:
conn = socket(AF_INET, SOCK_STREAM)
conn.connect((targetHost, targetPort))
print '[+] Connection to ' + targetHost + ' port ' + str(targetPort) + ' succeeded!' grab(conn)
...
def grab(conn):
try:
conn.send('Hello, is it me you\'re looking for? \r\n')
ret = conn.recv(1024)
print '[+]' + str(ret)
return
except Exception, e:
print '[-] Unable to grab any information: ' + str(e)
return
We are able to grab the banner from the Apache service running on my DVL machine, but not the Apache2 service running on my Ubuntu machine. That’s because the more up-to-date HTTP services require specific input for it to return its banner.
So here’s a little tweak – introduce grabHTTP() and edit the existing conn() function.
def conn(targetHost, targetPort):
try:
...
if targetPort == 80:
grabHTTP(conn)
else:
grab(conn)
...
def grabHTTP(conn):
try:
conn.send('GET HTTP/1.1 \r\n')
ret = conn.recv(1024)
print '[+]' + str(ret)
return
except Exception, e:
print '[-] Unable to grab any information: ' + str(e)
return
What Now? Why Do This?
By the end of this, you may be feeling a little excited that you've coded your own port scanner. But an afterthought might follow – “why do this when there are so many freely available port scanning tools out there?” – “Why write a Python script that uses Nmap when it’s easier to use Nmap itself?”
First, because coding is fun. Second, this can be just the beginning of writing your own automated exploit script. You can make your script fires up tools such as Metasploit and exploit hosts based on your reconnaissance results, etc. – all using one simple script, and not yourself scrambling through all your tools that are scattered all over your system.
Reference
T.J. O’Connor’s very well written book – Violent Python, 1st ed., Syngress, Novber 2008.
Author
Emil Tan, Skipper & Co-Founder of Div0.