Python for Ethical Hacking: Building a Port Scanner

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setup
  4. Building the Port Scanner
    1. Scanning a Single Port
    2. Scanning Multiple Ports
    3. Handling Exceptions
    4. Scanning a Range of Ports
  5. Conclusion

Introduction

In the world of ethical hacking, a port scanner is a crucial tool for discovering open ports on a target system. Python, with its robust networking capabilities and vast libraries, provides an excellent platform to build a port scanner from scratch. In this tutorial, you will learn how to utilize Python to create a simple yet effective port scanner. By the end of this tutorial, you will be able to write Python code to scan for open ports on a target system.

Prerequisites

To follow along with this tutorial, you should have a basic understanding of Python programming concepts, including variables, loops, and functions. Additionally, a basic knowledge of networking concepts such as TCP/IP and ports would be beneficial.

Setup

Before we begin building the port scanner, we need to ensure that Python is installed on our system. You can download the latest version of Python from the official website (python.org) and follow the installation instructions for your operating system.

Once Python is installed, you can verify its installation by opening a command prompt or terminal and running the following command: python python --version If Python is correctly installed, you will see the version number printed on the screen.

Building the Port Scanner

Scanning a Single Port

Let’s start by building a basic port scanner that scans a single port on a target system. We will use the socket module in Python, which provides low-level networking functionalities.

First, import the socket module: python import socket Next, define a function to perform the port scan: ```python def scan_port(target_host, target_port): try: # Create a socket object client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # Set a timeout value (in seconds)
        client_socket.settimeout(1)
        
        # Try to connect to the target host and port
        result = client_socket.connect_ex((target_host, target_port))
        
        # Check if the port is open
        if result == 0:
            print(f"Port {target_port} is open")
        else:
            print(f"Port {target_port} is closed")
        
        # Close the socket
        client_socket.close()
    except socket.error:
        print("An error occurred while connecting to the target")
``` In the `scan_port` function, we create a socket object using `socket.socket()`. We then set a timeout value of 1 second using `settimeout()` to prevent the program from waiting indefinitely if the connection attempt takes too long. Next, we use `connect_ex()` to attempt a connection to the target host and port. If the result is 0, it means the port is open. Otherwise, the port is closed.

To test the port scanner, call the scan_port function with the target host and port number: python scan_port("127.0.0.1", 80) Replace "127.0.0.1" with the IP address of the target system and 80 with the desired port number.

Scanning Multiple Ports

Now, let’s enhance our port scanner to scan multiple ports. Instead of scanning a single port, we will provide a list of ports to scan.

Modify the scan_port function as follows: ```python def scan_ports(target_host, port_list): for port in port_list: try: # Create a socket object client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

            # Set a timeout value (in seconds)
            client_socket.settimeout(1)
            
            # Try to connect to the target host and port
            result = client_socket.connect_ex((target_host, port))
            
            # Check if the port is open
            if result == 0:
                print(f"Port {port} is open")
            else:
                print(f"Port {port} is closed")
            
            # Close the socket
            client_socket.close()
        except socket.error:
            print("An error occurred while connecting to the target")
``` In the `scan_ports` function, we iterate over the `port_list` and call the `scan_port` function for each port.

To test the new functionality, provide a list of ports to scan: python target_ports = [80, 443, 22, 3389] scan_ports("127.0.0.1", target_ports) Replace "127.0.0.1" with the IP address of the target system and [80, 443, 22, 3389] with the desired list of port numbers.

Handling Exceptions

When scanning multiple ports, it’s important to handle exceptions gracefully and continue scanning even if an error occurs for a particular port. Let’s modify the code to handle exceptions and display a meaningful error message. ```python def scan_ports(target_host, port_list): for port in port_list: try: # Create a socket object client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

            # Set a timeout value (in seconds)
            client_socket.settimeout(1)
            
            # Try to connect to the target host and port
            result = client_socket.connect_ex((target_host, port))
            
            # Check if the port is open
            if result == 0:
                print(f"Port {port} is open")
            else:
                print(f"Port {port} is closed")

        except socket.gaierror:
            print("Invalid target hostname or IP address")
        except socket.timeout:
            print(f"Timeout occurred while connecting to port {port}")
        except ConnectionRefusedError:
            print(f"Connection refused while connecting to port {port}")
        except Exception as e:
            print(f"An error occurred while connecting to port {port}: {str(e)}")

        finally:
            # Close the socket
            client_socket.close()
``` In the modified code, we added specific exception handlers for common error scenarios such as an invalid target hostname/IP address, timeout, and connection refused. Additionally, we added a generic exception handler to catch any other exceptional scenarios. Finally, we moved the socket closing logic to the `finally` block to ensure the socket is closed regardless of any exception that occurs.

Scanning a Range of Ports

To further enhance our port scanner, let’s add the capability to scan a range of ports. Instead of providing a list of individual ports, we will specify a range of ports to scan.

Modify the scan_ports function again: ```python def scan_ports(target_host, start_port, end_port): for port in range(start_port, end_port + 1): try: # Create a socket object client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

            # Set a timeout value (in seconds)
            client_socket.settimeout(1)
            
            # Try to connect to the target host and port
            result = client_socket.connect_ex((target_host, port))
            
            # Check if the port is open
            if result == 0:
                print(f"Port {port} is open")
            else:
                print(f"Port {port} is closed")

        except socket.gaierror:
            print("Invalid target hostname or IP address")
        except socket.timeout:
            print(f"Timeout occurred while connecting to port {port}")
        except ConnectionRefusedError:
            print(f"Connection refused while connecting to port {port}")
        except Exception as e:
            print(f"An error occurred while connecting to port {port}: {str(e)}")

        finally:
            # Close the socket
            client_socket.close()
``` In the updated code, we use the `range()` function to generate a range of ports from `start_port` to `end_port`. The `end_port + 1` is used to include the `end_port` in the range.

To scan a range of ports, simply call the scan_ports function with the target host and the desired range: python scan_ports("127.0.0.1", 1, 1024) Replace "127.0.0.1" with the IP address of the target system and 1 and 1024 with the desired start and end ports.

Conclusion

In this tutorial, you learned how to build a simple port scanner using Python. We started by scanning a single port and gradually enhanced the scanner to support scanning multiple ports and ranges of ports. We also explored exception handling to handle various error scenarios that may arise during the scanning process. By following this tutorial, you now have the necessary knowledge to start building more advanced and sophisticated network scanning tools with Python.

Remember, always use your knowledge and skills responsibly and ethically. Happy hacking!


Note: This tutorial is for educational purposes only. Ethical hacking should only be performed with proper authorization and legal consent.