SHARE
TWEET

Untitled

a guest Feb 11th, 2019 63 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python2
  2.  
  3. import socket
  4. import netifaces
  5. import struct
  6. import json
  7. import re
  8. from netaddr import IPNetwork, EUI
  9. import threading
  10. import binascii
  11. import time
  12. import errno
  13. from Queue import Queue
  14.  
  15. # actual port scanner
  16. def p_scan(jdict, iface, plock, tar_ip, port):
  17.     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  18.     s.settimeout(0.25)
  19.  
  20.     try:
  21.         c = s.connect((tar_ip, port))
  22.         #resp = s.recv(1024)
  23.         #print(len(resp))
  24.         with plock:
  25.             print('\t\t...discovered open port %s on %s.' % (port, tar_ip))
  26.             jdict["machines"][iface][tar_ip]["tcp"][str(port)] = "unknown"
  27.  
  28.         c.close()
  29.     except:
  30.         pass
  31.  
  32. # threader for port scanner
  33. def threader(jdict, iface, q, plock, tar_ip):
  34.     while True:
  35.         p = q.get()
  36.         p_scan(jdict, iface, plock, tar_ip, p)
  37.         q.task_done()
  38.  
  39. # port scanner for all IPs found on each interface
  40. def scan_ports(jdict, iface):
  41.     plock = threading.Lock()
  42.  
  43.     for ip in jdict["machines"][iface].keys():
  44.         tar_ip = socket.gethostbyname(ip)
  45.    
  46.         q = Queue()
  47.  
  48.         for x in range(50):
  49.             t = threading.Thread(target = threader, args=(jdict, iface, q, plock, tar_ip))
  50.             t.daemon = True
  51.             t.start()
  52.    
  53.         for p in range(1, 500):
  54.             q.put(p)
  55.  
  56.         q.join()
  57.  
  58. # find interface from jdict based on IP and MAC
  59. def loc_iface(jdict, dst_ip4, dst_mac):
  60.     for iface in jdict["machines"]:
  61.         if dst_ip4 in jdict["machines"][iface].keys():
  62.             #print('found ip4 %s in iface %s' % (dst_ip4, iface))
  63.             if jdict["machines"][iface][dst_ip4]["mac"] == dst_mac:
  64.                 #print('found mac %s' % (dst_mac))
  65.                 return iface
  66.  
  67. # handle ARP replies
  68. def recv_sock(s, jdict):
  69.     resp = s.recvfrom(1024)
  70.  
  71.     eth_hdr = resp[0][0:14]
  72.     eth_det = struct.unpack("!6s6s2s", eth_hdr)
  73.  
  74.     arp_hdr = resp[0][14:42]
  75.     arp_det = struct.unpack("2s2s1s1s2s6s4s6s4s", arp_hdr)
  76.  
  77.     # skip non-ARP packets
  78.     etype = eth_det[2]
  79.     if etype != '\x08\x06':
  80.         #print('\t\t\t... non-arp packet')
  81.         return 0
  82.  
  83.     src_mac = str(EUI(binascii.hexlify(arp_det[5]))).replace('-', ':')
  84.     src_ip4 = socket.inet_ntoa(arp_det[6])
  85.     dst_mac = str(EUI(binascii.hexlify(arp_det[7]))).replace('-', ':')
  86.     dst_ip4 = socket.inet_ntoa(arp_det[8])
  87.  
  88.     iface = loc_iface(jdict, dst_ip4, dst_mac)
  89.     #print('\t...received ARP reply on interface %s from\n\t\tIP: %s\n\t\tMAC: %s\n' % (iface, src_ip4, src_mac))
  90.  
  91.     # I don't care about what I accidentily pick up between other machines
  92.     if iface is None:
  93.         return 0
  94.  
  95.     jdict["machines"][iface][src_ip4] = {}
  96.     jdict["machines"][iface][src_ip4]["mac"] = src_mac
  97.     jdict["machines"][iface][src_ip4]["tcp"] = {}
  98.  
  99.     return 1
  100.  
  101. # send an ARP request to every IP in the subnet for the provided interface
  102. def iter_sock(jdict, nmdict, iface):
  103.     print('\tBeginning ARP scan for interface %s.' % (iface))
  104.     s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(3))
  105.     s.bind((iface, 0))
  106.  
  107.     s.settimeout(.02)
  108.  
  109.     iface_ip = jdict["machines"][iface].keys()[0]
  110.     iface_nm = nmdict[iface]
  111.  
  112.     ptime = time.time()
  113.     count = 0
  114.        
  115.     for ip in IPNetwork(iface_ip + "/" + iface_nm):
  116.         src_mac = binascii.unhexlify(str(jdict["machines"][iface][iface_ip]["mac"]).replace(':', '')) # source MAC
  117.         src_ip4 = iface_ip                              # source IP
  118.         dst_mac = '\xff\xff\xff\xff\xff\xff'            # target MAC
  119.         dst_ip4 = str(ip)                                    # target IP
  120.  
  121.         # ethernet header
  122.         protocol = 0x0806                   # 0x0806 for ARP
  123.         eth_hdr = struct.pack("!6s6sH", dst_mac, src_mac, protocol)
  124.  
  125.         # ARP header
  126.         htype = 1                           # hardware type is ethernet
  127.         ptype = 0x0800                      # protocol type is TCP
  128.         hlen = 6                            # hardware addr len is 6
  129.         plen = 4                            # protocol addr len is 4
  130.         opcode = 1                          # opcode 1 = request
  131.         src = socket.inet_aton(src_ip4)
  132.         dst = socket.inet_aton(dst_ip4)
  133.         arp_hdr = struct.pack("!HHBBH6s4s6s4s", htype, ptype, hlen, plen, opcode, src_mac, src, dst_mac, dst)
  134.  
  135.         packet = eth_hdr + arp_hdr
  136.         try:
  137.             s.send(packet)
  138.         except socket.error as e:
  139.             if e.errno == errno.ENETDOWN:
  140.                 print('\t...network was down on interface %s.' % (iface))
  141.             return
  142.  
  143.         try:
  144.             count = count + recv_sock(s, jdict)
  145.  
  146.             # print status every 8 seconds
  147.             if time.time() - ptime > 8:
  148.                 ptime = time.time()
  149.                 print('\t...received %d ARP replies on interface %s' % (count, iface))
  150.         except socket.timeout:
  151.             #print('... socket timed out, moving on...')
  152.             continue
  153.  
  154.     s.close()
  155.     print('\tCompleted ARP scan for interface %s with %d replies.' % (iface, count))
  156.  
  157. # initialize ARP request process for all interfaces
  158. def scan_net(jdict, nmdict):
  159.     print('Starting ARP scan on all discovered interfaces.\n')
  160.     thread_list = []
  161.  
  162.     # setup concurrent processeses for all ARP requests
  163.     for iface in nmdict:
  164.         # uncomment the following line, and comment the 3 after that, to run arp reqests without multithreading
  165.         #iter_sock(jdict, nmdict, iface)
  166.         t = threading.Thread(target=iter_sock, args=(jdict, nmdict, iface))
  167.         t.start()
  168.         thread_list.append(t)
  169.  
  170.      # wait for all processes to complete
  171.     for t in thread_list:
  172.         t.join()
  173.  
  174. # obtain local interface information and initialize json dictionary
  175. def init_local():
  176.     jdict = {}
  177.     jdict["machines"] = {}
  178.  
  179.     nmdict = {}
  180.    
  181.     # get interfaces on host machine
  182.     ipv4 = ""
  183.     mac = ""
  184.     netmask = ""
  185.  
  186.     for iface in netifaces.interfaces():
  187.         # ignore localhost interface
  188.         if iface == 'lo' or iface == 'wlp2s0':
  189.             continue
  190.  
  191.         addresses = netifaces.ifaddresses(iface)
  192.         for inet_type in addresses:
  193.             for _addr in addresses[inet_type]:
  194.                 if re.match(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$', _addr["addr"]):
  195.                     mac = _addr["addr"]
  196.                 if re.match(r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$', _addr["addr"]):
  197.                     ipv4 = _addr["addr"]
  198.                     netmask = _addr["netmask"]
  199.         print('Located interface...\n\tName: %s\n\tIPv4: %s\n\tMAC:  %s\n\tNetmask: %s\n' % (iface, ipv4, mac, netmask))
  200.         jdict["machines"][iface] = {}
  201.         jdict["machines"][iface][ipv4] = {}
  202.         jdict["machines"][iface][ipv4]["mac"] = mac.upper()
  203.         jdict["machines"][iface][ipv4]["tcp"] = {}
  204.  
  205.         nmdict[iface] = netmask
  206.    
  207.     print(str(jdict) + '\n')
  208.     print(str(nmdict) + '\n')
  209.     print('JSON dict succesfully initialized with all local interfaces.')
  210.     print('Netmask dict successfully loaded with all interfaces and their netmasks.\n')
  211.     print('Moving on to network scan...')
  212.  
  213.     return (jdict, nmdict)
  214.  
  215. if __name__ == "__main__":
  216.     (jdict, nmdict) = init_local()
  217.     scan_net(jdict, nmdict)
  218.  
  219.     # we've gotten all the devices, now port scan them
  220.     for iface in jdict["machines"]:
  221.         print('Beginning port scan for interface %s.' % (iface))
  222.         scan_ports(jdict, iface)
  223.  
  224.     with open("results.json", "w") as results:
  225.         json.dump(jdict, results, sort_keys=True, indent=4)
  226.  
  227.     results.close()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top