Today I am going to go through a python scanner included in the learning path of pnpt-live.
The script is very simple and will have many flaws, but can be used as POC.
#!/bin/python
import sys
import socket
from datetime import datetimetry: #Here we define the hostname/IP to scan
if len(sys.argv) == 2:
target = socket.gethostbyname(sys.argv[1]) #just in case it is a hostname
else:
print("Invalid")
#some banners
print ("-" * 20)
print ("Scanning - " + target)
print (str(datetime.now()))
print ("-" * 20)
for port in range(20,200):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.setdefaulttimeout(1)
result = s.connect_ex((target,port)) #returns an error, if 0, no error, port open. If 1, there is an error, port closed
if result == 0:
print("Port {} is open".format(port))
s.close()except socket.gaierror:#dns resolution does not work
print("Hostname not resolved.")
sys.exit()except KeyboardInterrupt: #ctrl+c
print("Program exit!")
sys.exit()
except socket.error:#no connection/inet
print("Could not connect to target")
sys.exit()
Let us go part by part:
#!/bin/python
import sys
import socket
from datetime import datetime
Our first line will declare that we are using python.
Rest of the imports will be used for:
- sys: We need to import the host or ip declared by argument (eg python scanner.py <ip>) by the sys.argv
- socket: node to node connection, we will need this.
- datetime: to import date library and write the time we are starting the scan.
We will also add a try/catch:
except socket.gaierror:#dns resolution does not work
print("Hostname not resolved.")
sys.exit()
except KeyboardInterrupt: #ctrl+c
print("Program exit!")
sys.exit()
except socket.error:#no connection/inet
print("Could not connect to target")
sys.exit()
In case that the hostname is not resolved, we interrupt the program or there is no connection to the target.
We obtain the hostname/ip from the argument and we verify:
if len(sys.argv) == 2:
target = socket.gethostbyname(sys.argv[1]) #just in case it is a hostname
else:
print("Invalid")
And the rest is just a banner:
print ("-" * 20)
print ("Scanning - " + target)
print (str(datetime.now()))
print ("-" * 20)
which will print the following:
The last part will be scanner itself:
for port in range(20,200):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.setdefaulttimeout(1)
result = s.connect_ex((target,port)) #returns an error, if 0, no error, port open. If 1, there is an error, port closed
if result == 0:
print("Port {} is open".format(port))
s.close()
In this case, I have decided to scan from port 20 to 200. but we could include any range we want, til 65535.
If the result of connect_ex(target,port) is 0, there are no errors, and we can conclude the port is open, proceeding to print it.
I have decided to put the whole code block with the try even though the teacher’s solution was starting after printing the banner, because I was getting an error: hostname: Name or service not known after socket.gethostbyname(sys.argv[1]).
To test it out, I gathered my router’s IP:
To know what ports were open without any doubts, I first check with nmap:
And now with our custom scanner:
None of the other ports will appear because of the range. It took around 20 seconds to get it, but I guess it can be tweak somehow with the timouts.
Feel free to leave any questions