So I decided to write a simple python port scanner but I wanted it to support to TCP, UDP, port ranges (22,23,135-139,443,445,3389 etc) and IP ranges(192.168.0.1/24, 192.168.10-20, example.com)
I also wanted to limit the libraries I used for use on locked down systems, thus, we only use socket, sys and argparse.
The first thing to do was get the code working for a single host and then slowly add bits to it in order to get it working. This is alpha, so your mileage may vary but here it is. Credit to Brandon Sterne as I ripped apart his code for a python CIDR converter.
1 2 3 4 5 6 7 8 9 10 11 12 13 | usage: nmap.py [-h] [-v] [-sS] [-sU] [-p PORTS] [-t TARGETS] nmap.py - Replicates limited nmap functionality in python optional arguments: -h, --help show this help message and exit -v, --verbose Enable this for full output -sS, --tcpscan Enable this for TCP scans -sU, --udpscan Enable this for UDP scans -p PORTS, --ports PORTS The ports you want to scan (21,22,80,135-139,443,445) -t TARGETS, --targets TARGETS The target(s) you want to scan (192.168.0.1) |
And then the code: (but better to download from github)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | #------------------------------------------------------------------------------- # Name: nmap.py # Purpose: Replicates limited nmap functionality using python # Author: phillipsme # Created: 12/08/2014 # Copyright: (c) phillipsme 2014 # Licence: Free to use, free to have fun! # Version: alpha!!! (0.1) # ToDo: verbose,dont do reverse lookup #------------------------------------------------------------------------------- import socket import argparse import sys def main(): parser = argparse.ArgumentParser(description='nmap.py - Replicates limited nmap functionality in python') parser.add_argument('-v', '--verbose', action='store_true', help='Enable this for full output') parser.add_argument('-sS', '--tcpscan', action='store_true', help='Enable this for TCP scans') parser.add_argument('-sU', '--udpscan', action='store_true', help='Enable this for UDP scans') parser.add_argument('-p', '--ports', default='1-1024', help='The ports you want to scan (21,22,80,135-139,443,445)') parser.add_argument('-t', '--targets', help='The target(s) you want to scan (192.168.0.1)') if len(sys.argv)==1: parser.print_help(); sys.exit(0) args = parser.parse_args() # Set target (and convert for FQDN) targets=[] if args.targets: if '/' in args.targets: #found cidr target targets = returnCIDR(args.targets) elif '-' in args.targets: targets = iprange(args.targets) else: try: targets.append(socket.gethostbyname(args.targets)) # get IP from FQDN except: errormsg("Failed to translate hostname to IP address") else: parser.print_help(); errormsg("You need to set a hostname") # Set ports if args.ports == '-': args.ports = '1-65535' ranges = (x.split("-") for x in args.ports.split(",")) ports = [i for r in ranges for i in range(int(r[0]), int(r[-1]) + 1)] # Output command line args to screen if args.verbose: printmsg("Arguments used:"); print args ; # Start Scanning for target in targets: tcpports, udpports = portscan(target,ports,args.tcpscan,args.udpscan,args.verbose) def portscan(target,ports,tcp,udp,verbose): #target=IPaddr,ports=list of ports,tcp=true/false,udp=true/false,verbose=true/false printmsg(("Now scanning %s" % (target))) tcpports=[] udpports=[] if tcp: for portnum in ports: try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(0.01) s.connect((target, portnum)) except Exception: failvar = 0 if verbose: print "%d/tcp \tclosed" % (portnum) else: print "%d/tcp \topen"% (portnum) tcpports.append(portnum) s.close() if udp: for portnum in ports: try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(0.1) s.sendto("--TEST LINE--", (target, portnum)) recv, svr = s.recvfrom(255) except Exception, e: try: errno, errtxt = e except ValueError: print "%d/udp \topen"% (portnum) udpports.append(portnum) else: if verbose: print "%d/udp \tclosed" % (portnum) s.close() printmsg(("%i open TCP ports, %i open UDP ports of %i ports scanned" % (len(tcpports),len(udpports),len(ports)))) return tcpports, udpports def errormsg(msg): print "[!] Error: %s" % (msg) ; sys.exit(1) def printmsg(msg): print "[+] nmap.py: %s" % (msg) def iprange(addressrange): # converts a ip range into a list list=[] first3octets = '.'.join(addressrange.split('-')[0].split('.')[:3]) + '.' for i in range(int(addressrange.split('-')[0].split('.')[3]),int(addressrange.split('-')[1])+1): list.append(first3octets+str(i)) return list def ip2bin(ip): b = "" inQuads = ip.split(".") outQuads = 4 for q in inQuads: if q != "": b += dec2bin(int(q),8); outQuads -= 1 while outQuads > 0: b += "00000000"; outQuads -= 1 return b def dec2bin(n,d=None): s = "" while n>0: if n&1: s = "1"+s else: s = "0"+s n >>= 1 if d is not None: while len(s)<d: s = "0"+s if s == "": s = "0" return s def bin2ip(b): ip = "" for i in range(0,len(b),8): ip += str(int(b[i:i+8],2))+"." return ip[:-1] def returnCIDR(c): parts = c.split("/") baseIP = ip2bin(parts[0]) subnet = int(parts[1]) ips=[] if subnet == 32: return bin2ip(baseIP) else: ipPrefix = baseIP[:-(32-subnet)] for i in range(2**(32-subnet)): ips.append(bin2ip(ipPrefix+dec2bin(i, (32-subnet)))) return ips if __name__ == '__main__': main() |
And for the sample output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | C:\Users\phillipsme\Documents>python nmap.py -sS -sU -p 22,23,80,123,135-139,427,443,445,3389,8081-8082 -t 127.0.0.1/30 [+] nmap.py: Now scanning 127.0.0.0 22/udp open 23/udp open 80/udp open 123/udp open 135/udp open 136/udp open 137/udp open 138/udp open 139/udp open 427/udp open 443/udp open 445/udp open 3389/udp open 8081/udp open 8082/udp open [+] nmap.py: 0 open TCP ports, 15 open UDP ports of 15 ports scanned [+] nmap.py: Now scanning 127.0.0.1 135/tcp open 445/tcp open 3389/tcp open 8081/tcp open 123/udp open 427/udp open 3389/udp open 8081/udp open 8082/udp open [+] nmap.py: 4 open TCP ports, 5 open UDP ports of 15 ports scanned [+] nmap.py: Now scanning 127.0.0.2 135/tcp open 445/tcp open 3389/tcp open 8081/tcp open 123/udp open 427/udp open 3389/udp open 8081/udp open 8082/udp open [+] nmap.py: 4 open TCP ports, 5 open UDP ports of 15 ports scanned [+] nmap.py: Now scanning 127.0.0.3 135/tcp open 445/tcp open 3389/tcp open 8081/tcp open 123/udp open 427/udp open 3389/udp open 8081/udp open 8082/udp open [+] nmap.py: 4 open TCP ports, 5 open UDP ports of 15 ports scanned C:\Users\phillipsme\Documents> |
Leave a Reply
You must be logged in to post a comment.