Port scanning is very important technique to probe a host for open ports. We can define it as trying to connect to the host from a list of ports, with the goal of finding an active ports and identifying running services on a targest to pentest it.
We can connect to any machine attached to the network using TCP/IP Protocol, by providing it's address and port number. Port number varies from 1 to 65536.
As a result of scan on a port, we can get:
[+] Open or Accepted: The host established a connection
[+] Closed, Denied or Not Listening: The specified port is closed
In port scanning there are many techniques, but in this post we will discover the most known one called "TCP Full Connect Scan" which is based on standard socket APIs.
Sockets provides an application-programming interface (API) that can be used in our programs to perform network communications between hosts. we can create socket object, connect to a host, bind our socket to a specified port, listen for connection, send and receive data through TCP/IP sockets.
Python supports sockets as well through it's module called "socket", so as first step to use sockets in our script, we need to import this library
after that we can use any of the following functions
[+] socket.gethostbyname(hostname): this function returns the IP address of the given domain name
[+] socket.gethostbyaddr(ip): return the domain name of the specified ip address
[+]socket.socket(family, type, proto): this function create an instance of the specified socket family (AF_INET, AF_INET6, AF_UNIX). the type argument can be SOCK_STREAM for TCP socket or SOCK_DGRAM for a UDP socket. the proto is almost set to zero
[+] socket.create((host, port)): this function take a tuple as parameter, this tuple contains the host and the port you want to connect to, and it tries to establish a connection with the target. if it fails, it triggers an exception.
[+] socket.send(data): we use this function to send data to the target after we establish a connection with it. the type of data should be byte.
[+] socket.recv(number of bytes): to receive data from host, we use this function by specifiying the size of data we want to accept.
[+] setdefaulttimeout(timeout): set the default timeout in seconds for the socket.
To build our own port scanner we will use the socket API mentioned above. to be more organized, i splited the script into 4 functions:
[+] h2ip: This function converts a hostname to ip address
[+] connecto: connects to the given (host, port) and returns a socket instance in case of connection established.
[+] bgrabber: This is a useful one, it sends a junk data to the host, and waits to receive banner of the service running on the specified port.
[+] scan: This function is used to call the two recent functions and display informations
This function will take the host submitted by the user and convert it to IP address. we're going to use gethostbyname(), in case the host is not valid, this function triggers an exception.
3.2. Establish a connection with the host
First, we create a socket instance of AF_INET address family (host, port) and SOCK_STREAM (TCP Socket) type. Then we try to establish a connection using connect(), if it succeed to connect we return the socket instance for future use, else, it triggers an exception.
3.3. Banner grabbing
After we connect to the target on the specified port, we try to send a data to the host in order to receive data about the running service. The recv() function kicks an exception when the timeout is reached.
3.3. Running the scan
The scan() function is used to call the above functions and display the scan information in a convenient way. It starts with connecto() to connect with the host, if a connection establishd, it calls bgrabber() to grab information on the service listening to the specified port. After done, it closes the socket instance.
Putting everything together and adding some option parsing to produce our own port scanner.