Search code examples
pythonfunctionipportport-scanning

python Port scanner that reads ports from . txt


My issue is that I have a ports.txt file in it has 4 port numbers. I wish for this program to scan all port numbers specified within the txt file. currently It will only scan the first port number listed in the txt file against the 40 odd IP addresses. I hope my formatting is correct and my detail is enough. ty

import socket
import os
import sys
from datetime import datetime
import win32evtlogutil
import win32evtlog
def main():
### call step 1 function

    ipList = network_addr()
   
    # call step 2 function

    portList = read_ports()
    print(portList)

    #call step 3 function
    for ip in ipList:
        for port in portList:
            scan_ports(ip,port)
    # call step 4 function
    report_to_EventViewer(ipList[0:10], 2) # warning
    #report_to_EventViewer(ipList, 1) # error
# processing inputs   
# Step 1: process input 1 (subnet or network address):
def network_addr():      
    while True:
        ip_list = []
        subnet_Addr = input('Enter a Class-C Network Address or subnet with format (x.x.x): ')
        subnet = subnet_Addr.split('.') # subnet is a list of 3 items (octets) 
        try:
            if (len(subnet)==3 and 192<=int(subnet[0])<=223 and 0<=int(subnet[1])<=255 and 0<=int(subnet[2])<=255):
                #return subnet_Addr
                print('valid subnet: ',subnet_Addr)
                for ip in range(11,40,2):
                    ip_temp = subnet_Addr + '.' + str(ip)
                    ip_list.append(ip_temp)
                return ip_list
            else:
                value = 'wrong subnet entered'
                print(value)
        except ValueError:
            print('wrong subnet entered, octects must be digits')
# Step 2: process input 2 (read port numbers from ports.txt): 
def read_ports():
    
    with open("ports.txt", 'r') as file_path:
        port_list = []
        for port in file_path:
                try:
                    if int(port) in port_list:
                        print(f'port: {port} already exists')
                    else:
                        port_list.append(int(port))
                except:
                        print(f'the port number: {port} is not a valid integer')  
                return port_list
        else:
            print('ports.txt is empty \n .... Exiting Port Scan App')
            sys.exit()

# Step 3: scan ports
def scan_ports(ip,port):
    # to get and format system time
    dateTimeObj = datetime.now()
    timeStamp = dateTimeObj.strftime("%d-%b-%Y (%H:%M:%S)")
    try:
        # open log file
        with open("ip_port_log.txt","+r") as log:
            # create client socket
            socket.setdefaulttimeout(0.1)
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            result = sock.connect_ex((ip,port))
            if result == 0:
                data = "IP:" + ip + ":" + str(port) + " Open " + timeStamp
                # write_to_console or display on screen
                print(data)
                # write in log file
                log.write(data + "\n")
            else:
                data = "IP:" + ip + ":" + str(port) + " Closed/Filtered or host is offline " + timeStamp
                # write_to_console or display on screen
                print(data)
                # write in log file
                log.write(data + "\n")
                # close the client socket
                sock.close()
                
    
    except socket.error:
            print("Can't connect to IP: ", ip)
            sys.exit()
    except KeyboardInterrupt:
        print("User pressed Ctrl+c")
        sys.exit()
# Step 4: Report to Event Viewer
# output 3
def report_to_EventViewer(mylist, eventtype):
        IP_EVT_APP_NAME = " CheckIPPort - IP-Port Scan Application"
        IP_EVT_ID = 7040  ##According to ???
        IP_EVT_CATEG = 9876  ##According to ???
        IP_EVT_TYPE = win32evtlog.EVENTLOG_WARNING_TYPE  # WARNING=2
        IP_EVT_ERR = win32evtlog.EVENTLOG_ERROR_TYPE  # ERROR=1
        IP_EVT_STRS = mylist
        IP_EVT_DATA = b"Scan IP Address Event Data"
        win32evtlogutil.ReportEvent(IP_EVT_APP_NAME, \
                                    IP_EVT_ID, \
                                    eventCategory=IP_EVT_CATEG, \
                                    eventType=eventtype, \
                                    strings=IP_EVT_STRS, \
                                    data=IP_EVT_DATA)

main()

Solution

  • you issue is in your read_ports method, you return inside the loop so it will ALWAYS only read the first one. Rewrite the method to something like:

    def read_ports():
        
    with open("ports.txt", 'r') as file_path:
        port_list = []
        for port in file_path:
                try:
                    if int(port) in port_list:
                        print(f'port: {port} already exists')
                    else:
                        port_list.append(int(port))
                except:
                        print(f'the port number: {port} is not a valid integer')  
        if not len(port_list):
            print('ports.txt is empty \n .... Exiting Port Scan App')
            sys.exit()
        return port_list