Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python2
- import socket
- import netifaces
- import struct
- import json
- import re
- from netaddr import IPNetwork, EUI
- import threading
- import binascii
- import time
- import errno
- from Queue import Queue
- # actual port scanner
- def p_scan(jdict, iface, plock, tar_ip, port):
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.settimeout(0.25)
- try:
- c = s.connect((tar_ip, port))
- #resp = s.recv(1024)
- #print(len(resp))
- with plock:
- print('\t\t...discovered open port %s on %s.' % (port, tar_ip))
- jdict["machines"][iface][tar_ip]["tcp"][str(port)] = "unknown"
- c.close()
- except:
- pass
- # threader for port scanner
- def threader(jdict, iface, q, plock, tar_ip):
- while True:
- p = q.get()
- p_scan(jdict, iface, plock, tar_ip, p)
- q.task_done()
- # port scanner for all IPs found on each interface
- def scan_ports(jdict, iface):
- plock = threading.Lock()
- for ip in jdict["machines"][iface].keys():
- tar_ip = socket.gethostbyname(ip)
- q = Queue()
- for x in range(50):
- t = threading.Thread(target = threader, args=(jdict, iface, q, plock, tar_ip))
- t.daemon = True
- t.start()
- for p in range(1, 500):
- q.put(p)
- q.join()
- # find interface from jdict based on IP and MAC
- def loc_iface(jdict, dst_ip4, dst_mac):
- for iface in jdict["machines"]:
- if dst_ip4 in jdict["machines"][iface].keys():
- #print('found ip4 %s in iface %s' % (dst_ip4, iface))
- if jdict["machines"][iface][dst_ip4]["mac"] == dst_mac:
- #print('found mac %s' % (dst_mac))
- return iface
- # handle ARP replies
- def recv_sock(s, jdict):
- resp = s.recvfrom(1024)
- eth_hdr = resp[0][0:14]
- eth_det = struct.unpack("!6s6s2s", eth_hdr)
- arp_hdr = resp[0][14:42]
- arp_det = struct.unpack("2s2s1s1s2s6s4s6s4s", arp_hdr)
- # skip non-ARP packets
- etype = eth_det[2]
- if etype != '\x08\x06':
- #print('\t\t\t... non-arp packet')
- return 0
- src_mac = str(EUI(binascii.hexlify(arp_det[5]))).replace('-', ':')
- src_ip4 = socket.inet_ntoa(arp_det[6])
- dst_mac = str(EUI(binascii.hexlify(arp_det[7]))).replace('-', ':')
- dst_ip4 = socket.inet_ntoa(arp_det[8])
- iface = loc_iface(jdict, dst_ip4, dst_mac)
- #print('\t...received ARP reply on interface %s from\n\t\tIP: %s\n\t\tMAC: %s\n' % (iface, src_ip4, src_mac))
- # I don't care about what I accidentily pick up between other machines
- if iface is None:
- return 0
- jdict["machines"][iface][src_ip4] = {}
- jdict["machines"][iface][src_ip4]["mac"] = src_mac
- jdict["machines"][iface][src_ip4]["tcp"] = {}
- return 1
- # send an ARP request to every IP in the subnet for the provided interface
- def iter_sock(jdict, nmdict, iface):
- print('\tBeginning ARP scan for interface %s.' % (iface))
- s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(3))
- s.bind((iface, 0))
- s.settimeout(.02)
- iface_ip = jdict["machines"][iface].keys()[0]
- iface_nm = nmdict[iface]
- ptime = time.time()
- count = 0
- for ip in IPNetwork(iface_ip + "/" + iface_nm):
- src_mac = binascii.unhexlify(str(jdict["machines"][iface][iface_ip]["mac"]).replace(':', '')) # source MAC
- src_ip4 = iface_ip # source IP
- dst_mac = '\xff\xff\xff\xff\xff\xff' # target MAC
- dst_ip4 = str(ip) # target IP
- # ethernet header
- protocol = 0x0806 # 0x0806 for ARP
- eth_hdr = struct.pack("!6s6sH", dst_mac, src_mac, protocol)
- # ARP header
- htype = 1 # hardware type is ethernet
- ptype = 0x0800 # protocol type is TCP
- hlen = 6 # hardware addr len is 6
- plen = 4 # protocol addr len is 4
- opcode = 1 # opcode 1 = request
- src = socket.inet_aton(src_ip4)
- dst = socket.inet_aton(dst_ip4)
- arp_hdr = struct.pack("!HHBBH6s4s6s4s", htype, ptype, hlen, plen, opcode, src_mac, src, dst_mac, dst)
- packet = eth_hdr + arp_hdr
- try:
- s.send(packet)
- except socket.error as e:
- if e.errno == errno.ENETDOWN:
- print('\t...network was down on interface %s.' % (iface))
- return
- try:
- count = count + recv_sock(s, jdict)
- # print status every 8 seconds
- if time.time() - ptime > 8:
- ptime = time.time()
- print('\t...received %d ARP replies on interface %s' % (count, iface))
- except socket.timeout:
- #print('... socket timed out, moving on...')
- continue
- s.close()
- print('\tCompleted ARP scan for interface %s with %d replies.' % (iface, count))
- # initialize ARP request process for all interfaces
- def scan_net(jdict, nmdict):
- print('Starting ARP scan on all discovered interfaces.\n')
- thread_list = []
- # setup concurrent processeses for all ARP requests
- for iface in nmdict:
- # uncomment the following line, and comment the 3 after that, to run arp reqests without multithreading
- #iter_sock(jdict, nmdict, iface)
- t = threading.Thread(target=iter_sock, args=(jdict, nmdict, iface))
- t.start()
- thread_list.append(t)
- # wait for all processes to complete
- for t in thread_list:
- t.join()
- # obtain local interface information and initialize json dictionary
- def init_local():
- jdict = {}
- jdict["machines"] = {}
- nmdict = {}
- # get interfaces on host machine
- ipv4 = ""
- mac = ""
- netmask = ""
- for iface in netifaces.interfaces():
- # ignore localhost interface
- if iface == 'lo' or iface == 'wlp2s0':
- continue
- addresses = netifaces.ifaddresses(iface)
- for inet_type in addresses:
- for _addr in addresses[inet_type]:
- if re.match(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$', _addr["addr"]):
- mac = _addr["addr"]
- 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"]):
- ipv4 = _addr["addr"]
- netmask = _addr["netmask"]
- print('Located interface...\n\tName: %s\n\tIPv4: %s\n\tMAC: %s\n\tNetmask: %s\n' % (iface, ipv4, mac, netmask))
- jdict["machines"][iface] = {}
- jdict["machines"][iface][ipv4] = {}
- jdict["machines"][iface][ipv4]["mac"] = mac.upper()
- jdict["machines"][iface][ipv4]["tcp"] = {}
- nmdict[iface] = netmask
- print(str(jdict) + '\n')
- print(str(nmdict) + '\n')
- print('JSON dict succesfully initialized with all local interfaces.')
- print('Netmask dict successfully loaded with all interfaces and their netmasks.\n')
- print('Moving on to network scan...')
- return (jdict, nmdict)
- if __name__ == "__main__":
- (jdict, nmdict) = init_local()
- scan_net(jdict, nmdict)
- # we've gotten all the devices, now port scan them
- for iface in jdict["machines"]:
- print('Beginning port scan for interface %s.' % (iface))
- scan_ports(jdict, iface)
- with open("results.json", "w") as results:
- json.dump(jdict, results, sort_keys=True, indent=4)
- results.close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement