python1

In this tutorial we will demonstrate how to make network connections with Python by building a basic port scanner.  What we will be doing is making a network socket connection over and over again based on a ip/port combination.  In order to accomplish this we will introduce a new concept, the for loop:

>>>
>>> for port in range(1000,1024):
...   print "[+] The port is: "+str(port)
...
[+] The port is: 1000
[+] The port is: 1001
[+] The port is: 1002
[+] The port is: 1003
[+] The port is: 1004
[+] The port is: 1005
[+] The port is: 1006
[+] The port is: 1007
[+] The port is: 1008
[+] The port is: 1009
[+] The port is: 1010
[+] The port is: 1011
[+] The port is: 1012
[+] The port is: 1013
[+] The port is: 1014
[+] The port is: 1015
[+] The port is: 1016
[+] The port is: 1017
[+] The port is: 1018
[+] The port is: 1019
[+] The port is: 1020
[+] The port is: 1021
[+] The port is: 1022
[+] The port is: 1023

Note that in the code snippet above the body of the for loop is indented.  Normally people indent by 2 spaces or with a tab, it doesn’t matter as long as you are consistent throughout the script.  To make the simple port scanner we will replace the print statement with a code snippet that makes a socket connection.  The code below shows how to make a socket connection using the built-in socket module:

>>>
>>> import socket
>>>
>>> s = socket.socket()
>>> s.connect(('127.0.0.1', 22))
>>> s.send('Primal Security n')
17
>>> banner = s.recv(1024)
>>> print banner
OpenSSH

Above we import the socket module and call the connect() function to connect to the given IP address and port number.  This will establish a TCP connection (SYN/SYN-ACK/ACK) and we actually send data to the given service with the send() function, and print the response with recv().  Now socket will throw an exception if the port isn’t open:

>>>
>>> s.connect(('127.0.0.1', 23))
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<string>", line 1, in connect
socket.error: (111, 'Connection refused')

This can be solved in a number of ways.  For now we will use a very simple way and use a “try/except” loop and just pass the exception:

>>>
>>> try:
...   s.connect(('127.0.0.1', 23))
... except: pass
...
>>>

Notice no errors!  Great way to make your code look like its working :).  Now lets combine all these concepts and make a quick for loop port scanner:

>>>
>>> for port in range(20,25):
...   try:
...    print "[+] Attempting to connect to 127.0.0.1:"+str(port)
...     s.connect(('127.0.0.1', port))
...     s.send('Primal Security n')    
...     banner = s.recv(1024)
...     if banner:
...       print "[+] Port "+str(port)+" open: "+banner
...     s.close()
...   except: pass
...
17
[+] Attempting to connect to 127.0.0.1:20
[+] Attempting to connect to 127.0.0.1:21
[+] Attempting to connect to 127.0.0.1:22
[+] Port 22 open: OpenSSH
[+] Attempting to connect to 127.0.0.1:23
[+] Attempting to connect to 127.0.0.1:24
[+] Attempting to connect to 127.0.0.1:25

Above we demonstrate the basic usage of the “try/except” loop to pass the exception thrown by socket when the port is closed.  We also show how to leverage a basic conditional statement with “if” to only attempt to print the port is open if the port responded to our probe.  Another way to create a port scanner would be to define a list of ports you’d like scanned with an array and then loop through the array:

>>>
>>> ports = [22, 445, 80, 443, 3389]
>>> for port in ports:
...   print port
...
22
445
80
443
3389
>>>

If we wanted to handle multiple hosts at once we would leverage a nested for loop.  This will involve an outter layer for loop that will loop through the hosts and an inner for loop that will loop through the ports.  Below is a basic example of how a nested for loop can be leveraged to make a slightly more complex scanner:

>>>
>>> hosts = ['127.0.0.1', '192.168.1.5', '10.0.0.1']
>>>
>>> ports = [22, 445, 80, 443, 3389]
>>>
>>> for host in hosts:
...   for port in ports:
...     try:
...        print "[+] Connecting to "+host+":"+str(port)
...        s.connect((host, port))
...        s.send('Primal Security n')
...        banner = s.recv(1024)
...        if banner:
...          print "[+] Port "+str(port)+" open: "+banner
...        s.close()
...     except:pass
...
[+] Connecting to 127.0.0.1:22
[+] Port 22 open: OpenSSH
[+] Connecting to 127.0.0.1:445
[+] Connecting to 127.0.0.1:80
[+] Connecting to 127.0.0.1:443
[+] Connecting to 127.0.0.1:3389
[+] Connecting to 192.168.1.5:22
[+] Connecting to 192.168.1.5:445
[+] Connecting to 192.168.1.5:80
[+] Connecting to 192.168.1.5:443
[+] Connecting to 192.168.1.5:3389
[+] Connecting to 10.0.0.1:22
[+] Connecting to 10.0.0.1:445
[+] Connecting to 10.0.0.1:80
[+] Connecting to 10.0.0.1:443
[+] Connecting to 10.0.0.1:3389

As you can see by the output, it loops the hosts array and attempts each port in the ports array then moves on to the next host.  For the final port scanner you might want to modify your print statements to only print ports that are open.

At the end of the day you will find that Nmap is still a far better option for port scanning, but we will build on these concepts in later blog posts to accomplish some more practical use cases.  Take some time to explore the various functions available within the socket module “dir(socket)”.