def __init__(self): self.Base = Base() self.ArpScan = ArpScan() self.ICMPv6Scan = ICMPv6Scan() if not self.Base.check_installed_software("nmap"): exit(2)
class ArpScanTest(unittest.TestCase): # region Properties path.append(dirname(dirname(dirname(dirname(dirname(abspath(__file__))))))) from raw_packet.Scanners.arp_scanner import ArpScan from raw_packet.Tests.Unit_tests.variables import Variables arp_scan: ArpScan = ArpScan() # endregion def test01_scan(self): arp_scan_results = self.arp_scan.scan( network_interface=ArpScanTest.Variables.test_network_interface, timeout=1, retry=1, show_scan_percentage=False) self.assertIsNotNone(arp_scan_results) find_router_mac: bool = False find_router_ip: bool = False for arp_scan_result in arp_scan_results: if arp_scan_result[ 'mac-address'] == ArpScanTest.Variables.router_mac_address: find_router_mac = True if arp_scan_result[ 'ip-address'] == ArpScanTest.Variables.router_ipv4_address: find_router_ip = True self.assertTrue(find_router_mac) self.assertTrue(find_router_ip) def test02_scan_with_exclude(self): arp_scan_results = self.arp_scan.scan( network_interface=ArpScanTest.Variables.test_network_interface, timeout=1, retry=1, show_scan_percentage=False, exclude_ip_addresses=[ArpScanTest.Variables.router_ipv4_address], exit_on_failure=False) find_router_mac: bool = False find_router_ip: bool = False for arp_scan_result in arp_scan_results: if arp_scan_result[ 'mac-address'] == ArpScanTest.Variables.router_mac_address: find_router_mac = True if arp_scan_result[ 'ip-address'] == ArpScanTest.Variables.router_ipv4_address: find_router_ip = True self.assertFalse(find_router_mac) self.assertFalse(find_router_ip) def test03_get_mac_address(self): mac_address = self.arp_scan.get_mac_address( network_interface=ArpScanTest.Variables.test_network_interface, target_ip_address=ArpScanTest.Variables.router_ipv4_address, timeout=1, retry=1, show_scan_percentage=False) self.assertEqual(mac_address, ArpScanTest.Variables.router_mac_address)
def get_free_ipv4_addresses(self, network_interface: str, first_ipv4_address: Union[None, str] = None, last_ipv4_address: Union[None, str] = None, quiet: bool = False) -> List[str]: your = self._base.get_interface_settings( interface_name=network_interface, required_parameters=[ 'mac-address', 'ipv4-address', 'first-ipv4-address', 'last-ipv4-address' ]) arp_scan: ArpScan = ArpScan(network_interface=network_interface) free_ipv4_addresses: List[str] = list() if first_ipv4_address is not None: current_ipv4_address: str = self.check_ipv4_address( network_interface=network_interface, ipv4_address=first_ipv4_address, is_local_ipv4_address=True, parameter_name='first IPv4 address') else: current_ipv4_address: str = your['first-ipv4-address'] if last_ipv4_address is not None: last_ipv4_address: str = self.check_ipv4_address( network_interface=network_interface, ipv4_address=last_ipv4_address, is_local_ipv4_address=True, parameter_name='last IPv4 address') else: last_ipv4_address: str = your['last-ipv4-address'] while self._base.ip_address_compare(current_ipv4_address, last_ipv4_address, 'le'): free_ipv4_addresses.append(current_ipv4_address) current_ipv4_address = self._base.ip_address_increment( current_ipv4_address) if not quiet: self._base.print_info('Find free IPv4 addresses on interface: ', your['network-interface']) alive_hosts = arp_scan.scan( timeout=5, retry=5, check_vendor=False, exclude_ip_addresses=[your['ipv4-address']], exit_on_failure=False, show_scan_percentage=False) for alive_host in alive_hosts: try: free_ipv4_addresses.remove(alive_host['ip-address']) except ValueError: pass return free_ipv4_addresses
Base.print_info("Wait 10 sec. before sniff packets from target: " + mac_address) sleep(10) # Add 5 packets to number of WiFi deauth packets deauth_packets_number += 5 # endregion # region Main function if __name__ == "__main__": # region Variables Scanner = Scanner() ArpScan = ArpScan() ICMPv6Scan = ICMPv6Scan() DnsServer = DnsServer() TM = ThreadManager(5) ip_pattern = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") target_mac_address = None target_ip_address = None new_target_ip_address = None target_apple_device = None first_suffix = 2 last_suffix = 255 network_prefix = None
class Scanner: # region Variables Base = None ArpScan = None ICMPv6Scan = None # endregion # region Init def __init__(self): self.Base = Base() self.ArpScan = ArpScan() self.ICMPv6Scan = ICMPv6Scan() if not self.Base.check_installed_software("nmap"): exit(2) # endregion # region Apple device selection def apple_device_selection(self, apple_devices): try: apple_device = None if len(apple_devices) > 0: if len(apple_devices) == 1: apple_device = apple_devices[0] self.Base.print_info("Only one Apple device found:") self.Base.print_success( apple_device[0] + " (" + apple_device[1] + ") ", apple_device[2]) if len(apple_devices) > 1: self.Base.print_info("Apple devices found:") device_index = 1 apple_devices_pretty_table = PrettyTable([ self.Base.cINFO + 'Index' + self.Base.cEND, self.Base.cINFO + 'IP address' + self.Base.cEND, self.Base.cINFO + 'MAC address' + self.Base.cEND, self.Base.cINFO + 'Vendor' + self.Base.cEND ]) for apple_device in apple_devices: apple_devices_pretty_table.add_row([ str(device_index), apple_device[0], apple_device[1], apple_device[2] ]) device_index += 1 print apple_devices_pretty_table device_index -= 1 current_device_index = raw_input( self.Base.c_info + 'Set device index from range (1-' + str(device_index) + '): ') if not current_device_index.isdigit(): self.Base.print_error("Your input data is not digit!") exit(1) if any([ int(current_device_index) < 1, int(current_device_index) > device_index ]): self.Base.print_error( "Your number is not within range (1-" + str(device_index) + ")") exit(1) current_device_index = int(current_device_index) - 1 apple_device = apple_devices[current_device_index] else: self.Base.print_error("Could not find Apple devices!") exit(1) return apple_device except KeyboardInterrupt: self.Base.print_info("Exit") exit(0) # endregion # region IPv6 device selection def ipv6_device_selection(self, ipv6_devices): try: ipv6_device = None if len(ipv6_devices) > 0: if len(ipv6_devices) == 1: ipv6_device = ipv6_devices[0] self.Base.print_info("Only one IPv6 device found:") self.Base.print_success( ipv6_device[0] + " (" + ipv6_device[1] + ") ", ipv6_device[2]) if len(ipv6_devices) > 1: self.Base.print_info("IPv6 devices found:") device_index = 1 for ipv6_device in ipv6_devices: self.Base.print_success( str(device_index) + ") " + ipv6_device[0] + " (" + ipv6_device[1] + ") ", ipv6_device[2]) device_index += 1 device_index -= 1 current_device_index = raw_input( self.Base.c_info + 'Set device index from range (1-' + str(device_index) + '): ') if not current_device_index.isdigit(): self.Base.print_error("Your input data is not digit!") exit(1) if any([ int(current_device_index) < 1, int(current_device_index) > device_index ]): self.Base.print_error( "Your number is not within range (1-" + str(device_index) + ")") exit(1) current_device_index = int(current_device_index) - 1 ipv6_device = ipv6_devices[current_device_index] else: self.Base.print_error("Could not find IPv6 devices!") exit(1) return ipv6_device except KeyboardInterrupt: self.Base.print_info("Exit") exit(0) # endregion # region Find all devices in local network def find_ip_in_local_network(self, network_interface, timeout=3, retry=3): try: local_network_ip_addresses = [] arp_scan_results = self.ArpScan.scan(network_interface, timeout, retry) if len(arp_scan_results) > 0: for device in arp_scan_results: if self.Base.ip_address_validation(device['ip-address']): local_network_ip_addresses.append(device['ip-address']) return local_network_ip_addresses except KeyboardInterrupt: self.Base.print_info("Exit") exit(0) # endregion # region Find Apple devices in local network with ArpScan def find_apple_devices_by_mac(self, network_interface, timeout=3, retry=3): try: apple_devices = [] arp_scan_results = self.ArpScan.scan(network_interface, timeout, retry) if len(arp_scan_results) > 0: for device in arp_scan_results: if "Apple" in device['vendor']: apple_devices.append([ device['ip-address'], device['mac-address'], device['vendor'] ]) else: self.Base.print_error( "Could not find devices in local network on interface: ", network_interface) exit(2) return apple_devices except KeyboardInterrupt: self.Base.print_info("Exit") exit(0) # endregion # region Find Apple devices in local network with ICMPv6 scan def find_apple_devices_by_mac_ipv6(self, network_interface, timeout=3, retry=3): try: apple_devices = [] icmpv6_scan_results = self.ICMPv6Scan.scan(network_interface, timeout, retry, None, True) if len(icmpv6_scan_results) > 0: for device in icmpv6_scan_results: if "Apple" in device['vendor']: apple_devices.append([ device['ip-address'], device['mac-address'], device['vendor'] ]) else: self.Base.print_error( "Could not find devices in local network on interface: ", network_interface) exit(2) return apple_devices except KeyboardInterrupt: self.Base.print_info("Exit") exit(0) # endregion # region Find IPv6 devices in local network with ICMPv6Scan def find_ipv6_devices(self, network_interface, timeout=5, retry=3, exclude_ipv6_address=None): try: ipv6_devices = [] ipv6_scan_results = self.ICMPv6Scan.scan(network_interface, timeout, retry, None, True) if len(ipv6_scan_results) > 0: for device in ipv6_scan_results: if exclude_ipv6_address is not None: if exclude_ipv6_address != device['ip-address']: ipv6_devices.append([ device['ip-address'], device['mac-address'], device['vendor'] ]) else: ipv6_devices.append([ device['ip-address'], device['mac-address'], device['vendor'] ]) else: self.Base.print_error( "Could not find devices with IPv6 link local address " + "in local network on interface: ", network_interface) exit(2) return ipv6_devices except KeyboardInterrupt: self.Base.print_info("Exit") exit(0) # endregion # region Find Apple devices in local network with nmap def find_apple_devices_with_nmap(self, network_interface): try: local_network_devices = [] apple_devices = [] local_network = self.Base.get_netiface_first_ip(network_interface) + "-" + \ self.Base.get_netiface_last_ip(network_interface).split('.')[3] nmap_process = sub.Popen([ 'nmap ' + local_network + ' -n -O --osscan-guess -T5 -e ' + network_interface + ' -oX ' + current_path + '/nmap_local_network.xml' ], shell=True, stdout=sub.PIPE) nmap_process.wait() nmap_report = ET.parse(current_path + "/nmap_local_network.xml") root_tree = nmap_report.getroot() for element in root_tree: if element.tag == "host": state = element.find('status').attrib['state'] if state == 'up': ip_address = "" mac_address = "" description = "" for address in element.findall('address'): if address.attrib['addrtype'] == 'ipv4': ip_address = address.attrib['addr'] if address.attrib['addrtype'] == 'mac': mac_address = address.attrib['addr'] try: description = address.attrib[ 'vendor'] + " device" except KeyError: pass for os_info in element.find('os'): if os_info.tag == 'osmatch': try: description += ", " + os_info.attrib['name'] except TypeError: pass break local_network_devices.append( [ip_address, mac_address, description]) for network_device in local_network_devices: if "Apple" or "Mac OS" or "iOS" in network_device[2]: apple_devices.append(network_device) return apple_devices except OSError as e: if e.errno == errno.ENOENT: self.Base.print_error("Program: ", "nmap", " is not installed!") exit(1) else: self.Base.print_error( "Something went wrong while trying to run ", "`nmap`") exit(2) except KeyboardInterrupt: self.Base.print_info("Exit") exit(0)
Base.print_info("Your IP address: ", your_ip_address) Base.print_info("Your MAC address: ", your_mac_address) # If target IP address is set print target IP, else print first and last IP if args.target_ip is not None: Base.print_info("Target IP: ", args.target_ip) else: Base.print_info("First IP: ", first_ip_address) Base.print_info("Last IP: ", last_ip_address) Base.print_info("Timeout: ", str(args.timeout) + " sec.") Base.print_info("Retry: ", str(args.retry)) # endregion # region Start scanner arp_scan = ArpScan() results = arp_scan.scan(current_network_interface, args.timeout, args.retry, args.target_ip, True) # endregion # region Print results if len(results) > 0: Base.print_success("Found devices:") pretty_table = PrettyTable([Base.cINFO + 'IP address' + Base.cEND, Base.cINFO + 'MAC address' + Base.cEND, Base.cINFO + 'Vendor' + Base.cEND]) for result in results: pretty_table.add_row([result['ip-address'], result['mac-address'], result['vendor']]) print(pretty_table) else: Base.print_error("Could not find devices in local network on interface: ", current_network_interface) # endregion
class DnsResolver: """ DNS resolver class """ # DNS packet: # # 0 16 31 # +------------------+------------------+ # | Transaction ID | Flags | # +------------------+------------------+ # | Questions | Answer RRS | # +------------------+------------------+ # | Authority RRs | Additional RRs | # +------------------+------------------+ # | Queries ... # +---------------- ... # region Set variables # region Init Raw-packet classes base = Base() # type: Base arp_scan = ArpScan() # type: ArpScan dns = DNS_raw() # type: DNS_raw # endregion # region Variables domain = '' # type: str subdomains = list() # type: List[str] available_characters = list([ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '-' ]) # type: List[str] results = list() # type: List[Dict[str, str]] # endregion # endregion # region Init def __init__( self, network_interface, # type: str quiet=False # type: bool ): # type: (...) -> None """ Init class DnsResolver :param network_interface: Network interface (example: eth0) :param quiet: Quiet mode on if True, quiet mode off if False (default: False) """ # Set network interface for sending DNS queries self.network_interface = network_interface # type: str # Set quiet mode self.quiet = quiet # type: bool # Get MAC, IPv4 and IPv6 addresses for network interface self.your_mac_address = self.base.get_netiface_mac_address( self.network_interface) # type: str self.your_ipv4_address = self.base.get_netiface_ip_address( self.network_interface) # type: str self.your_ipv6_address = self.base.get_netiface_ipv6_link_address( self.network_interface, False) # type: str # __init__.__annotations__ = { # 'network_interface': str, # 'quiet': bool, # 'return': None # } # endregion # region Parse DNS packet function def _parse_packet( self, response # type: Dict[str, Dict[str, Union[str, Dict[str, str]]]] ): # type: (...) -> None """ Parse DNS answers :param response: DNS answer dictionary :return: None """ if 'DNS' in response.keys(): if len(response['DNS']['answers']) > 0: for answer in response['DNS']['answers']: if self.domain in answer['name']: if answer['type'] == 1: self.results.append({ 'Domain': answer['name'][:-1], 'IPv4 address': answer['address'], 'IPv6 address': '-' }) self.base.print_success('Domain: ', answer['name'][:-1], ' IPv4: ', answer['address']) if answer['type'] == 28: self.results.append({ 'Domain': answer['name'][:-1], 'IPv4 address': '-', 'IPv6 address': answer['address'] }) self.base.print_success('Domain: ', answer['name'][:-1], ' IPv6: ', answer['address']) # _parse_packet.__annotations__ = { # 'request': Dict[str, Dict[str, Union[str, Dict[str, str]]]], # 'return': None # } # endregion # region Sniff DNS packets function def _sniff_packets( self, destination_mac_address, # type: str destination_ipv4_address, # type: str destination_ipv6_address, # type: str source_port=53 # type: int ): # type: (...) -> None """ Sniff DNS answers :param destination_mac_address: Destination MAC address in DNS answer (most likely this is MAC address on your network interface) :param destination_ipv4_address: Destination IPv4 address in DNS answer (most likely this is IPv4 address on your network interface) :param destination_ipv6_address: Destination IPv6 address in DNS answer (most likely this is IPv6 address on your network interface) :param source_port: Source UDP port in DNS answer (default: 53 - default port for DNS servers) :return: None """ network_filters = { 'Ethernet': { 'destination': destination_mac_address }, 'IP': { 'destination-ip': destination_ipv4_address }, 'IPv6': { 'destination-ip': destination_ipv6_address }, 'UDP': { 'source-port': source_port } } sniff = Sniff_raw() sniff.start(protocols=['Ethernet', 'IP', 'IPv6', 'UDP', 'DNS'], prn=self._parse_packet, filters=network_filters) # _sniff_packets.__annotations__ = { # 'destination_mac_address': str, # 'destination_ipv4_address': str, # 'destination_ipv6_address': str, # 'source_port': int, # 'return': None # } # endregion # region Send DNS queries to IPv4 NS server def _send_ipv4_queries( self, source_mac_address, # type: str source_ipv4_address, # type: str ns_server_mac_address, # type: str ns_server_ipv4_address, # type: str ns_server_port, # type: int queries, # type: List[Dict[str, Union[int, str]]] send_socket # type: socket ): # type: (...) -> None """ Send DNS queries to IPv4 DNS servers :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface) :param source_ipv4_address: Source IPv4 address for DNS query (most likely this is IPv4 address on your network interface) :param ns_server_mac_address: DNS server MAC address for DNS query :param ns_server_ipv4_address: DNS server IPv4 address for DNS query :param ns_server_port: DNS server destination UDP port for DNS query (default: 53) :param queries: List of DNS queries for sending (example: [{'type': 1, 'class': 1, 'name': 'www.test.com'}]) :param send_socket: Raw socket for sending DNS queries :return: None """ for query in queries: # Set source UDP port and DNS transaction ID for sending DNS query udp_source_port = randint(2049, 65535) # type: int dns_transaction_id = randint(1, 65535) # type: int send_socket.send( self.dns.make_request_packet(src_mac=source_mac_address, dst_mac=ns_server_mac_address, src_ip=source_ipv4_address, dst_ip=ns_server_ipv4_address, src_port=udp_source_port, dst_port=ns_server_port, tid=dns_transaction_id, queries=[query])) # _send_ipv4_queries.__annotations__ = { # 'source_mac_address': str, # 'source_ipv4_address': str, # 'ns_server_mac_address': str, # 'ns_server_ipv4_address': str, # 'ns_server_port': int, # 'queries': List[Dict[str, Union[int, str]]], # 'send_socket': socket, # 'return': None # } # endregion # region Send IPv6 DNS queries to IPv6 NS server def _send_ipv6_queries( self, source_mac_address, # type: str source_ipv6_address, # type: str ns_server_mac_address, # type: str ns_server_ipv6_address, # type: str ns_server_port, # type: int queries, # type: List[Dict[str, Union[int, str]]] send_socket # type: socket ): # type: (...) -> None """ Send DNS queries to IPv6 DNS servers :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface) :param source_ipv6_address: Source IPv6 address for DNS query (most likely this is IPv6 address on your network interface) :param ns_server_mac_address: DNS server MAC address for DNS query :param ns_server_ipv6_address: DNS server IPv6 address for DNS query :param ns_server_port: DNS server destination UDP port for DNS query (default: 53) :param queries: List of DNS queries for sending (example: [{'type': 1, 'class': 1, 'name': 'www.test.com'}]) :param send_socket: Raw socket for sending DNS queries :return: None """ for query in queries: # Set source UDP port and DNS transaction ID for sending DNS query udp_source_port = randint(2049, 65535) # type: int dns_transaction_id = randint(1, 65535) # type: int send_socket.send( self.dns.make_request_packet(src_mac=source_mac_address, dst_mac=ns_server_mac_address, src_ip=source_ipv6_address, dst_ip=ns_server_ipv6_address, src_port=udp_source_port, dst_port=ns_server_port, tid=dns_transaction_id, queries=[query])) # _send_ipv6_queries.__annotations__ = { # 'source_mac_address': str, # 'source_ipv6_address': str, # 'ns_server_mac_address': str, # 'ns_server_ipv6_address': str, # 'ns_server_port': int, # 'queries': List[Dict[str, Union[int, str]]], # 'send_socket': socket, # 'return': None # } # endregion # region Send DNS queries function def _send_queries( self, send_socket, # type: socket source_mac_address, # type: str source_ipv4_address, # type: str source_ipv6_address, # type: str domain, # type: str ns_servers, # type: List[Dict[str, str]] destination_port=53, # type: int max_threats_count=9, # type: int subdomains=['www'], # type: List[str] queries_type=[1, 28], # type: List[int] queries_class=[1] # type: List[int] ): # type: (...) -> None """ Send DNS queries to IPv4/IPv6 DNS servers :param send_socket: Raw socket for sending DNS queries :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface) :param source_ipv4_address: Source IPv4 address for DNS query (most likely this is IPv4 address on your network interface) :param source_ipv6_address: Source IPv6 address for DNS query (most likely this is IPv6 address on your network interface) :param domain: Target domain (example: 'test.com') :param ns_servers: List of DNS servers (example: [{'ipv4 address': '8.8.8.8', 'mac address': '01:23:45:67:89:0a'}]) :param destination_port: UDP destination port (default: 53) :param max_threats_count: Maximum threats count (default: 9) :param subdomains: List of subdomains (default: ['www']) :param queries_type: List of queries type (default: [1, 28]; type 1: A, type 28: AAAA) :param queries_class: List of queries class (default: [1]; class 1: IN) :return: None """ # DNS query type: 1 (A) # DNS query type: 28 (AAAA) # DNS query class: 1 (IN) # region Init threat manager send_threats = ThreadManager(max_threats_count) # endregion # region Make DNS queries list queries = list() for subdomain in subdomains: for query_type in queries_type: for query_class in queries_class: queries.append({ 'type': query_type, 'class': query_class, 'name': subdomain + '.' + domain }) # endregion # region Calculate number of DNS queries for one threat queries_len = len(queries) ipv4_ns_servers_len = 0 ipv6_ns_servers_len = 0 for ns_server in ns_servers: if 'ipv4 address' in ns_server.keys(): ipv4_ns_servers_len += 1 if 'ipv6 address' in ns_server.keys(): ipv6_ns_servers_len += 1 if source_ipv6_address is not None: queries_len_for_threat = int( (queries_len * (ipv4_ns_servers_len + ipv6_ns_servers_len)) / max_threats_count) + 1 else: queries_len_for_threat = int( (queries_len * ipv4_ns_servers_len) / max_threats_count) + 1 # endregion # region Send DNS queries # region Send DNS queries to IPv4 NS servers for ns_server in ns_servers: if 'ipv4 address' in ns_server.keys(): for query_index in range(0, queries_len, queries_len_for_threat): send_threats.add_task( self._send_ipv4_queries, source_mac_address, source_ipv4_address, ns_server['mac address'], ns_server['ipv4 address'], destination_port, queries[query_index:query_index + queries_len_for_threat], send_socket) # endregion # region Send DNS queries to IPv6 NS servers if source_ipv6_address is not None: for ns_server in ns_servers: if 'ipv6 address' in ns_server.keys(): for query_index in range(0, queries_len, queries_len_for_threat): send_threats.add_task( self._send_ipv6_queries, source_mac_address, source_ipv6_address, ns_server['mac address'], ns_server['ipv6 address'], destination_port, queries[query_index:query_index + queries_len_for_threat], send_socket) # endregion # endregion # region Wait all threats send_threats.wait_for_completion() # endregion # _send_queries.__annotations__ = { # 'send_socket': socket, # 'source_mac_address': str, # 'source_ipv4_address': str, # 'domain': str, # 'ns_servers': List[Dict[str, str]], # 'destination_port': int, # 'max_threats_count': int, # 'subdomains': List[str], # 'queries_type': List[int], # 'queries_class': List[int], # 'return': None # } # endregion # region Main function: resolve def resolve( self, ns_servers, # type: List[Dict[str, str]] domain, # type: str subdomains_list=[], # type: List[str] subdomains_file=None, # type: str subdomains_brute=False, # type: bool max_threats_count=10, # type: int udp_destination_port=53, # type: int timeout=30 # type: int ): # type: (...) -> List[Dict[str, str]] """ DNS resolve all subdomains in target domain :param ns_servers: List of DNS servers (example: [{'ipv4 address': '8.8.8.8', 'mac address': '01:23:45:67:89:0a'}]) :param domain: Target domain (example: 'test.com') :param subdomains_list: List of subdomains (example: ['www','ns','mail']) :param subdomains_file: Name of file with subdomains (default: None) :param subdomains_brute: Brute mode on (auto make list with subdomains) if True, Brute mode off if False (default: False) :param max_threats_count: Maximum threats count (default: 10) :param udp_destination_port: UDP destination port (default: 53) :param timeout: Connection after send all DNS queries (default: 30) :return: List of dictionary (example: [{'Domain': 'www.test.com', 'IPv4 address': '1.2.3.4', 'IPv6 address': '-'}]) """ try: # region Set target domain assert not (domain is None or domain == ''), \ 'Target domain is empty, please set target domain in this parameter: ' + self.base.info_text('domain') self.domain = domain # endregion # region Subdomains list if len(subdomains_list) > 0: self.subdomains = subdomains_list # endregion # region Subdomains file if subdomains_file is not None: assert isfile(subdomains_file), \ 'File with subdomain list:' + self.base.error_text(subdomains_file) + ' not found!' with open(subdomains_file) as subdomains_file_descriptor: for subdomain in subdomains_file_descriptor.read( ).splitlines(): self.subdomains.append(subdomain) # endregion # region Subdomains brute if subdomains_brute: if not self.quiet: self.base.print_info( 'Make subdomains list for brute .... ') for character1 in self.available_characters: self.subdomains.append(character1) for character2 in self.available_characters: self.subdomains.append(character1 + character2) for character3 in self.available_characters: self.subdomains.append(character1 + character2 + character3) # endregion # region Check length of subdomains list assert len(self.subdomains) != 0, \ 'List containing subdomains is empty, please set any of this parameters: ' \ + self.base.info_text('subdomain_list') + ' or ' \ + self.base.info_text('subdomain_file') + ' or ' \ + self.base.info_text('subdomain_brute') # endregion # region Create raw socket raw_socket = socket(AF_PACKET, SOCK_RAW) raw_socket.bind((self.network_interface, 0)) # endregion # region Sniff DNS answers if not self.quiet: self.base.print_info('Start DNS answers sniffer ...') threats = ThreadManager(max_threats_count) threats.add_task(self._sniff_packets, self.your_mac_address, self.your_ipv4_address, self.your_ipv6_address, udp_destination_port) # endregion # region Send DNS queries if not self.quiet: self.base.print_info('Start sending DNS queries, time: ', str(datetime.now())) self._send_queries(send_socket=raw_socket, source_mac_address=self.your_mac_address, source_ipv4_address=self.your_ipv4_address, source_ipv6_address=self.your_ipv6_address, domain=domain, ns_servers=ns_servers, destination_port=udp_destination_port, max_threats_count=int(max_threats_count) - 1, subdomains=self.subdomains) # endregion # region Timeout if not self.quiet: self.base.print_info('Wait timeout: ', str(timeout) + ' sec') sleep(timeout) # endregion # region Return results return self.results # endregion except AssertionError as Error: self.base.print_error(Error.args[0]) exit(1)
__author__ = 'Vladimir Ivanov' __copyright__ = 'Copyright 2019, Raw-packet Project' __credits__ = [''] __license__ = 'MIT' __version__ = '0.2.1' __maintainer__ = 'Vladimir Ivanov' __email__ = '*****@*****.**' __status__ = 'Development' # endregion # region Main function if __name__ == '__main__': # region Init raw packet classes base: Base = Base() arp_scan: ArpScan = ArpScan() # endregion # region Check user and platform base.check_user() base.check_platform() # endregion # region Parse script arguments parser = ArgumentParser(description='DNS resolver') parser.add_argument('-i', '--interface', help='Set interface name for send DNS request packets', default=None) parser.add_argument('-s', '--nsservers_name', type=str, help='NS servers name (example: "ns1.test.com,ns2.test.com")', default=None) parser.add_argument('-n', '--nsservers_ip', type=str,
# endregion # region General output if not args.quiet: Base.print_info("Network interface: ", network_interface) Base.print_info("Gateway IP address: ", gateway_ip_address) Base.print_info("Your IP address: ", your_ip_address) Base.print_info("Your MAC address: ", your_mac_address) Base.print_info("First ip address: ", first_ip_address) Base.print_info("Last ip address: ", last_ip_address) # endregion # region Set target IP address target_ip_address = "1.1.1.1" target_mac_address = "00:00:00:00:00:00" arp_scan = ArpScan() if args.target_ip is None: Base.print_info("Start ARP scan ...") results = arp_scan.scan(network_interface, 3, 3, None, True, gateway_ip_address) if len(results) > 0: if len(results) == 1: target_ip_address = results[0]['ip-address'] target_mac_address = results[0]['mac-address'] else: Base.print_info("Network devices found:") hosts_pretty_table = PrettyTable([Base.cINFO + 'Index' + Base.cEND, Base.cINFO + 'IP address' + Base.cEND, Base.cINFO + 'MAC address' + Base.cEND, Base.cINFO + 'Vendor' + Base.cEND])
class Scanner: # region Variables base: Base = Base() arp_scan: ArpScan = ArpScan() icmpv6_scan: ICMPv6Scan = ICMPv6Scan() nmap_scan_result: str = current_path + '/nmap_scan.xml' # endregion # region Init def __init__(self): if not self.base.check_installed_software('nmap'): self.base.print_error('Could not find program: ', 'nmap') exit(1) # endregion # region Apple device selection def apple_device_selection( self, apple_devices: Union[None, List[List[str]]], exit_on_failure: bool = False) -> Union[None, List[str]]: try: assert apple_devices is not None, 'List of Apple devices is None!' assert len(apple_devices) != 0, 'List of Apple devices is empty!' for apple_device in apple_devices: assert len(apple_device) == 3, \ 'Bad list of Apple device, example: [["192.168.0.1", "12:34:56:78:90:ab", "Apple, Inc."]]' assert (self.base.ip_address_validation(ip_address=apple_device[0]) or self.base.ipv6_address_validation(ipv6_address=apple_device[0])), \ 'Bad list of Apple device, example: [["192.168.0.1", "12:34:56:78:90:ab", "Apple, Inc."]]' assert self.base.mac_address_validation(mac_address=apple_device[1]), \ 'Bad list of Apple device, example: [["192.168.0.1", "12:34:56:78:90:ab", "Apple, Inc."]]' apple_device: Union[None, List[str]] = None if len(apple_devices) == 1: apple_device = apple_devices[0] self.base.print_info('Only one Apple device found:') self.base.print_success( apple_device[0] + ' (' + apple_device[1] + ') ', apple_device[2]) if len(apple_devices) > 1: self.base.print_info('Apple devices found:') device_index: int = 1 apple_devices_pretty_table = PrettyTable([ self.base.cINFO + 'Index' + self.base.cEND, self.base.cINFO + 'IP address' + self.base.cEND, self.base.cINFO + 'MAC address' + self.base.cEND, self.base.cINFO + 'Vendor' + self.base.cEND ]) for apple_device in apple_devices: apple_devices_pretty_table.add_row([ str(device_index), apple_device[0], apple_device[1], apple_device[2] ]) device_index += 1 print(apple_devices_pretty_table) device_index -= 1 current_device_index = input( self.base.c_info + 'Set device index from range (1-' + str(device_index) + '): ') if not current_device_index.isdigit(): self.base.print_error('Your input data is not digit!') return None if any([ int(current_device_index) < 1, int(current_device_index) > device_index ]): self.base.print_error( 'Your number is not within range (1-' + str(device_index) + ')') return None current_device_index = int(current_device_index) - 1 apple_device = apple_devices[current_device_index] return apple_device except KeyboardInterrupt: self.base.print_info('Exit') exit(0) except AssertionError as Error: self.base.print_error(Error.args[0]) if exit_on_failure: exit(1) return None # endregion # region IPv4 device selection def ipv4_device_selection( self, ipv4_devices: Union[None, List[Dict[str, str]]], exit_on_failure: bool = False) -> Union[None, Dict[str, str]]: try: assert ipv4_devices is not None, 'List of IPv4 devices is None!' assert len(ipv4_devices) != 0, 'List of IPv4 devices is empty!' for ipv4_device in ipv4_devices: assert len(ipv4_device) == 3, \ 'Bad dict of IPv4 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert 'ip-address' in ipv4_device.keys(), \ 'Bad dict of IPv4 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert self.base.ip_address_validation(ipv4_device['ip-address']), \ 'Bad dict of IPv4 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert 'mac-address' in ipv4_device.keys(), \ 'Bad dict of IPv4 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert self.base.mac_address_validation(ipv4_device['mac-address']), \ 'Bad dict of IPv4 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert 'vendor' in ipv4_device.keys(), \ 'Bad dict of IPv4 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' ipv4_device: Union[None, Dict[str, str]] = None # region IPv4 devices is found # region Only one IPv4 device found if len(ipv4_devices) == 1: ipv4_device: Dict[str, str] = ipv4_devices[0] self.base.print_info('Only one IPv4 device found:') self.base.print_success(ipv4_device['ip-address'] + ' (' + ipv4_device['mac-address'] + ') ' + ipv4_device['vendor']) # endregion # region More than one IPv4 device found if len(ipv4_devices) > 1: self.base.print_success('Found ', str(len(ipv4_devices)), ' IPv4 alive hosts!') device_index: int = 1 pretty_table = PrettyTable([ self.base.info_text('Index'), self.base.info_text('IPv4 address'), self.base.info_text('MAC address'), self.base.info_text('Vendor') ]) for ipv4_device in ipv4_devices: pretty_table.add_row([ str(device_index), ipv4_device['ip-address'], ipv4_device['mac-address'], ipv4_device['vendor'] ]) device_index += 1 print(pretty_table) device_index -= 1 current_device_index: Union[int, str] = \ input(self.base.c_info + 'Set device index from range (1-' + str(device_index) + '): ') assert current_device_index.isdigit(), \ 'Your input data is not digit!' current_device_index: int = int(current_device_index) assert not any([current_device_index < 1, current_device_index > device_index]), \ 'Your number is not within range (1-' + str(device_index) + ')' current_device_index: int = int(current_device_index) - 1 ipv4_device: Dict[str, str] = ipv4_devices[current_device_index] # endregion # endregion # region IPv4 devices not found else: if exit_on_failure: self.base.print_error('Could not find IPv4 devices!') exit(1) # endregion return ipv4_device except KeyboardInterrupt: self.base.print_info('Exit') exit(0) except AssertionError as Error: self.base.print_error(Error.args[0]) if exit_on_failure: exit(1) return None # endregion # region IPv6 device selection def ipv6_device_selection( self, ipv6_devices: Union[None, List[Dict[str, str]]], exit_on_failure: bool = False) -> Union[None, Dict[str, str]]: try: assert ipv6_devices is not None, 'List of IPv6 devices is None!' assert len(ipv6_devices) != 0, 'List of IPv6 devices is empty!' for ipv6_device in ipv6_devices: assert len(ipv6_device) == 3, \ 'Bad dict of IPv6 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert 'ip-address' in ipv6_device.keys(), \ 'Bad dict of IPv6 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert self.base.ipv6_address_validation(ipv6_device['ip-address']), \ 'Bad dict of IPv6 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert 'mac-address' in ipv6_device.keys(), \ 'Bad dict of IPv6 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert self.base.mac_address_validation(ipv6_device['mac-address']), \ 'Bad dict of IPv6 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' assert 'vendor' in ipv6_device.keys(), \ 'Bad dict of IPv6 device, example: ' + \ '[{"ip-address": "fd00::1", "mac-address": "12:34:56:78:90:ab", "vendor": "Apple, Inc."}]' ipv6_device: Union[None, Dict[str, str]] = None # region IPv6 devices is found # region Only one IPv6 device found if len(ipv6_devices) == 1: ipv6_device: Dict[str, str] = ipv6_devices[0] self.base.print_info('Only one IPv6 device found:') self.base.print_success(ipv6_device['ip-address'] + ' (' + ipv6_device['mac-address'] + ') ' + ipv6_device['vendor']) # endregion # region More than one IPv6 device found if len(ipv6_devices) > 1: self.base.print_success('Found ', str(len(ipv6_devices)), ' IPv6 alive hosts!') device_index: int = 1 pretty_table = PrettyTable([ self.base.info_text('Index'), self.base.info_text('IPv6 address'), self.base.info_text('MAC address'), self.base.info_text('Vendor') ]) for ipv6_device in ipv6_devices: pretty_table.add_row([ str(device_index), ipv6_device['ip-address'], ipv6_device['mac-address'], ipv6_device['vendor'] ]) device_index += 1 print(pretty_table) device_index -= 1 current_device_index: Union[int, str] = \ input(self.base.c_info + 'Set device index from range (1-' + str(device_index) + '): ') assert current_device_index.isdigit(), \ 'Your input data is not digit!' current_device_index: int = int(current_device_index) assert not any([current_device_index < 1, current_device_index > device_index]), \ 'Your number is not within range (1-' + str(device_index) + ')' current_device_index: int = int(current_device_index) - 1 ipv6_device: Dict[str, str] = ipv6_devices[current_device_index] # endregion # endregion # region IPv6 devices not found else: if exit_on_failure: self.base.print_error('Could not find IPv6 devices!') exit(1) # endregion return ipv6_device except KeyboardInterrupt: self.base.print_info('Exit') exit(0) except AssertionError as Error: self.base.print_error(Error.args[0]) if exit_on_failure: exit(1) return None # endregion # region Find all devices in local network def find_ip_in_local_network( self, network_interface: str = 'eth0', timeout: int = 3, retry: int = 3, show_scan_percentage: bool = True, exit_on_failure: bool = True) -> Union[None, List[str]]: try: local_network_ip_addresses: List[str] = list() arp_scan_results = self.arp_scan.scan( network_interface=network_interface, timeout=timeout, retry=retry, exit_on_failure=False, check_vendor=True, show_scan_percentage=show_scan_percentage) assert len(arp_scan_results) != 0, \ 'Could not find network devices on interface: ' + self.base.error_text(network_interface) for device in arp_scan_results: if self.base.ip_address_validation(device['ip-address']): local_network_ip_addresses.append(device['ip-address']) return local_network_ip_addresses except KeyboardInterrupt: self.base.print_info('Exit') exit(0) except AssertionError as Error: self.base.print_error(Error.args[0]) if exit_on_failure: exit(1) return None # endregion # region Find Apple devices in local network with arp_scan def find_apple_devices_by_mac( self, network_interface: str = 'eth0', timeout: int = 3, retry: int = 3, show_scan_percentage: bool = True, exit_on_failure: bool = True) -> Union[None, List[List[str]]]: try: apple_devices: List[List[str]] = list() arp_scan_results = self.arp_scan.scan( network_interface=network_interface, timeout=timeout, retry=retry, exit_on_failure=False, check_vendor=True, show_scan_percentage=show_scan_percentage) assert len(arp_scan_results) != 0, \ 'Could not find network devices on interface: ' + self.base.error_text(network_interface) for device in arp_scan_results: if 'Apple' in device['vendor']: apple_devices.append([ device['ip-address'], device['mac-address'], device['vendor'] ]) assert len(apple_devices) != 0, \ 'Could not find Apple devices on interface: ' + self.base.error_text(network_interface) return apple_devices except KeyboardInterrupt: self.base.print_info('Exit') exit(0) except AssertionError as Error: self.base.print_error(Error.args[0]) if exit_on_failure: exit(1) return None # endregion # region Find Apple devices in local network with ICMPv6 scan def find_apple_devices_by_mac_ipv6( self, network_interface: str = 'eth0', timeout: int = 5, retry: int = 3, exit_on_failure: bool = True) -> Union[None, List[List[str]]]: try: apple_devices: List[List[str]] = list() icmpv6_scan_results = self.icmpv6_scan.scan( network_interface=network_interface, timeout=timeout, retry=retry, exit_on_failure=False, check_vendor=True) assert len(icmpv6_scan_results) != 0, \ 'Could not find IPv6 network devices on interface: ' + self.base.error_text(network_interface) for device in icmpv6_scan_results: if 'Apple' in device['vendor']: apple_devices.append([ device['ip-address'], device['mac-address'], device['vendor'] ]) assert len(apple_devices) != 0, \ 'Could not find Apple devices on interface: ' + self.base.error_text(network_interface) return apple_devices except KeyboardInterrupt: self.base.print_info('Exit') exit(0) except AssertionError as Error: self.base.print_error(Error.args[0]) if exit_on_failure: exit(1) return None # endregion # region Find IPv6 devices in local network with icmpv6_scan def find_ipv6_devices( self, network_interface: str = 'eth0', timeout: int = 5, retry: int = 3, exclude_ipv6_addresses: Union[None, List[str]] = None, exit_on_failure: bool = True) -> Union[None, List[Dict[str, str]]]: try: ipv6_devices: List[Dict[str, str]] = list() ipv6_scan_results = self.icmpv6_scan.scan( network_interface=network_interface, timeout=timeout, retry=retry, target_mac_address=None, check_vendor=True, exit_on_failure=False) assert len(ipv6_scan_results) != 0, \ 'Could not find IPv6 network devices on interface: ' + self.base.error_text(network_interface) for device in ipv6_scan_results: if exclude_ipv6_addresses is not None: if device['ip-address'] not in exclude_ipv6_addresses: ipv6_devices.append(device) else: ipv6_devices.append(device) assert len(ipv6_devices) != 0, \ 'Could not find IPv6 devices on interface: ' + self.base.error_text(network_interface) return ipv6_devices except KeyboardInterrupt: self.base.print_info('Exit') exit(0) except AssertionError as Error: self.base.print_error(Error.args[0]) if exit_on_failure: exit(1) return None # endregion # region Find Apple devices in local network with nmap def find_apple_devices_with_nmap( self, network_interface: str = 'eth0', exit_on_failure: bool = True) -> Union[None, List[List[str]]]: try: if isfile(Scanner.nmap_scan_result): remove(Scanner.nmap_scan_result) local_network_devices: List[List[str]] = list() apple_devices: List[List[str]] = list() local_network = self.base.get_first_ip_on_interface(network_interface) + '-' + \ self.base.get_last_ip_on_interface(network_interface).split('.')[3] self.base.print_info( 'Start nmap scan: ', 'nmap ' + local_network + ' -n -O --osscan-guess -T5 -e ' + network_interface + ' -oX ' + Scanner.nmap_scan_result) nmap_process = sub.Popen([ 'nmap ' + local_network + ' -n -O --osscan-guess -T5 -e ' + network_interface + ' -oX ' + Scanner.nmap_scan_result ], shell=True, stdout=sub.PIPE) nmap_process.wait() nmap_report = ET.parse(Scanner.nmap_scan_result) root_tree = nmap_report.getroot() for element in root_tree: if element.tag == 'host': state = element.find('status').attrib['state'] if state == 'up': ip_address: str = '' mac_address: str = '' description: str = '' for address in element.findall('address'): if address.attrib['addrtype'] == 'ipv4': ip_address = address.attrib['addr'] if address.attrib['addrtype'] == 'mac': mac_address = address.attrib['addr'].lower() try: description = address.attrib[ 'vendor'] + ' device' except KeyError: pass for os_info in element.find('os'): if os_info.tag == 'osmatch': try: description += ', ' + os_info.attrib['name'] except TypeError: pass break local_network_devices.append( [ip_address, mac_address, description]) assert len(local_network_devices) != 0, \ 'Could not find any devices on interface: ' + self.base.error_text(network_interface) for network_device in local_network_devices: if 'Apple' in network_device[2] or 'Mac OS' in network_device[ 2] or 'iOS' in network_device[2]: apple_devices.append(network_device) assert len(apple_devices) != 0, \ 'Could not find Apple devices on interface: ' + self.base.error_text(network_interface) return apple_devices except OSError: self.base.print_error('Something went wrong while trying to run ', '`nmap`') exit(2) except KeyboardInterrupt: self.base.print_info('Exit') exit(0) except AssertionError as Error: self.base.print_error(Error.args[0]) if exit_on_failure: exit(1) return None
def scan(interface: Union[None, str] = None, target_ip: Union[None, str] = None, timeout: int = 5, retry: int = 5): """ ARP scan :param interface: Network interface name for ARP scanner :param target_ip: Target IPv4 address :param timeout: Timeout (default=5) :param retry: Number of retry packets (default=5) :return: None """ # region Print banner base.print_banner(__script_name__) # endregion try: # region Get your network interface settings current_network_interface: str = \ base.network_interface_selection(interface_name=interface, message='Please select a network interface for ' + __script_name__ + ' from table: ') current_network_interface_settings: Dict[str, Union[None, str, List[str]]] = \ base.get_interface_settings(interface_name=current_network_interface, required_parameters=['mac-address', 'ipv4-address', 'first-ipv4-address', 'last-ipv4-address']) # endregion # region Target IP is set if target_ip is not None: utils: Utils = Utils() utils.check_ipv4_address( network_interface=current_network_interface, ipv4_address=target_ip, is_local_ipv4_address=True, parameter_name='target IPv4 address') # endregion # region General output base.print_info( 'Network interface: ', current_network_interface_settings['network-interface']) base.print_info('Your IP address: ', current_network_interface_settings['ipv4-address']) base.print_info('Your MAC address: ', current_network_interface_settings['mac-address']) # If target IP address is set print target IP, else print first and last IP if target_ip is not None: base.print_info('Target IP: ', target_ip) else: base.print_info( 'First IP: ', current_network_interface_settings['first-ipv4-address']) base.print_info( 'Last IP: ', current_network_interface_settings['last-ipv4-address']) base.print_info('Timeout: ', str(timeout) + ' sec.') base.print_info('Retry: ', str(retry)) # endregion # region Start scanner arp_scan: ArpScan = ArpScan( network_interface=current_network_interface) results: List[Dict[str, str]] = arp_scan.scan(timeout=timeout, retry=retry, target_ip_address=target_ip, check_vendor=True, exclude_ip_addresses=None, exit_on_failure=False, show_scan_percentage=True) # endregion # region Print results assert len(results) != 0, \ 'Could not find devices in local network on interface: ' + base.error_text(current_network_interface) if target_ip is None: base.print_success('Found ', str(len(results)), ' alive hosts on interface: ', current_network_interface) else: base.print_success('Found target: ', target_ip) pretty_table = PrettyTable([ base.cINFO + 'Index' + base.cEND, base.cINFO + 'IP address' + base.cEND, base.cINFO + 'MAC address' + base.cEND, base.cINFO + 'Vendor' + base.cEND ]) index: int = 1 for result in results: pretty_table.add_row([ index, result['ip-address'], result['mac-address'], result['vendor'] ]) index += 1 print(pretty_table) # endregion except KeyboardInterrupt: base.print_info('Exit') exit(0) except AssertionError as Error: base.print_error(Error.args[0]) exit(1)
class ArpScanTest(TestCase): # region Properties variables: Variables = Variables() arp_scan: ArpScan = ArpScan( network_interface=variables.your.network_interface) # endregion def test01_scan(self): arp_scan_results = self.arp_scan.scan(timeout=1, retry=1, show_scan_percentage=False, exit_on_failure=False) self.assertIsNotNone(arp_scan_results) find_router: bool = False find_target: bool = False for arp_scan_result in arp_scan_results: if arp_scan_result[ 'ip-address'] == self.variables.router.ipv4_address: self.assertEqual(arp_scan_result['mac-address'], self.variables.router.mac_address) self.assertIn(self.variables.router.vendor, arp_scan_result['vendor']) find_router = True if arp_scan_result[ 'ip-address'] == self.variables.target.ipv4_address: self.assertEqual(arp_scan_result['mac-address'], self.variables.target.mac_address) self.assertIn(self.variables.target.vendor, arp_scan_result['vendor']) find_target = True self.assertTrue(find_router) self.assertTrue(find_target) def test02_scan_with_exclude(self): arp_scan_results = self.arp_scan.scan( timeout=1, retry=1, show_scan_percentage=False, exclude_ip_addresses=[self.variables.router.ipv4_address], exit_on_failure=False) self.assertIsNotNone(arp_scan_results) find_router: bool = False find_target: bool = False for arp_scan_result in arp_scan_results: if arp_scan_result[ 'ip-address'] == self.variables.router.ipv4_address: find_router = True if arp_scan_result[ 'ip-address'] == self.variables.target.ipv4_address: self.assertEqual(arp_scan_result['mac-address'], self.variables.target.mac_address) self.assertIn(self.variables.target.vendor, arp_scan_result['vendor']) find_target = True self.assertFalse(find_router) self.assertTrue(find_target) def test03_get_mac_address(self): mac_address = self.arp_scan.get_mac_address( target_ip_address=self.variables.router.ipv4_address, timeout=1, retry=1, show_scan_percentage=False, exit_on_failure=False) self.assertEqual(mac_address, self.variables.router.mac_address) mac_address = self.arp_scan.get_mac_address( target_ip_address=self.variables.target.ipv4_address, timeout=1, retry=1, show_scan_percentage=False, exit_on_failure=False) self.assertEqual(mac_address, self.variables.target.mac_address)
class RawDnsResolver: """ DNS resolver class """ # DNS packet: # # 0 16 31 # +------------------+------------------+ # | Transaction ID | Flags | # +------------------+------------------+ # | Questions | Answer RRS | # +------------------+------------------+ # | Authority RRs | Additional RRs | # +------------------+------------------+ # | Queries ... # +---------------- ... # region Set properties # region Init Raw-packet classes base: Base = Base() arp_scan: ArpScan = ArpScan() dns: RawDNS = RawDNS() # endregion # region Variables domain: str = '' subdomains: List[str] = list() available_characters: List[str] = list([ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '-' ]) results: List[Dict[str, str]] = list() uniq_hosts: List[Dict[str, str]] = list() uniq_domains: List[str] = list() number_of_dns_queries: int = 0 index_of_dns_query: int = 0 percent_of_complete: int = 0 temporary_results_filename: str = '/tmp/dns_resolver_results.txt' tshark_process = None tshark_pcap_filename: str = '/tmp/dns_answers.pcap' tshark_number_of_dns_answers: int = 0 # endregion # endregion # region Init def __init__(self, network_interface: str = 'eth0', quiet: bool = False) -> None: """ Init class DnsResolver :param network_interface: Network interface (example: eth0) :param quiet: Quiet mode on if True, quiet mode off if False (default: False) """ # Set network interface for sending DNS queries self.network_interface: str = network_interface # Set quiet mode self.quiet: bool = quiet # Get MAC, IPv4 and IPv6 addresses for network interface self.your_mac_address: str = self.base.get_interface_mac_address( self.network_interface) self.your_ipv4_address: str = self.base.get_interface_ip_address( self.network_interface) self.your_ipv4_network: str = self.base.get_interface_network( self.network_interface) self.your_ipv6_address: str = self.base.get_interface_ipv6_link_address( self.network_interface, False) # endregion # region Write resolve results to file def _save_result(self, result: Dict[str, str]) -> None: try: self.results.append(result) if 'NS' in result.keys(): self.base.print_success('Domain: ', result['Domain'], ' NS: ', result['NS']) else: with open(RawDnsResolver.temporary_results_filename, 'a') as temporary_file: temporary_file.write('Domain: ' + result['Domain'] + ' IPv4 address: ' + result['IPv4 address'] + ' IPv6 address: ' + result['IPv6 address'] + '\n') if result['IPv6 address'] == '-': print(self.base.cSUCCESS + '[' + str(len(self.uniq_hosts)) + '] ' + self.base.cEND + result['Domain'] + ' - ' + result['IPv4 address']) else: print(self.base.cSUCCESS + '[' + str(len(self.uniq_hosts)) + '] ' + self.base.cEND + result['Domain'] + ' - ' + result['IPv6 address']) except AttributeError: pass except KeyError: pass # endregion # region Parse DNS packet function def _parse_packet(self, packet) -> None: """ Parse DNS answers :param packet: DNS packet :return: None """ try: assert packet.haslayer(IP), 'Is not IPv4 packet!' assert packet.haslayer(UDP), 'Is not UDP packet!' assert packet.haslayer(DNS), 'Is not DNS packet!' assert packet[ IP].dst == self.your_ipv4_address, 'Not your destination IPv4 address!' assert packet[UDP].sport == 53, 'UDP source port != 53' assert packet[DNS].ancount != 0, 'DNS answer is empty!' for answer_index in range(packet[DNS].ancount): dns_answer = packet[DNS].an[answer_index] name: bytes = dns_answer.rrname name: str = name.decode('utf-8')[:-1] assert self.domain in name, 'Not found target domain in DNS answer!' address: str = '' if isinstance(dns_answer.rdata, bytes): address: bytes = dns_answer.rdata address: str = address.decode('utf-8') if isinstance(dns_answer.rdata, str): address: str = dns_answer.rdata match_host = next( (host for host in self.uniq_hosts if host['name'] == name and host['address'] == address), None) if match_host is None: self.uniq_hosts.append({'name': name, 'address': address}) if dns_answer.type == 2: self._save_result({'Domain': name, 'NS': address}) if dns_answer.type == 1: self._save_result({ 'Domain': name, 'IPv4 address': address, 'IPv6 address': '-' }) if dns_answer.type == 28: self._save_result({ 'Domain': name, 'IPv4 address': '-', 'IPv6 address': address }) except AssertionError: pass except UnicodeDecodeError: pass # endregion # region Start tshark def _sniff_start(self, destination_mac_address: str, destination_ipv4_address: str, destination_ipv6_address: str, source_port: int = 53) -> None: """ Sniff DNS answers :param destination_mac_address: Destination MAC address in DNS answer (most likely this is MAC address on your network interface) :param destination_ipv4_address: Destination IPv4 address in DNS answer (most likely this is IPv4 address on your network interface) :param destination_ipv6_address: Destination IPv6 address in DNS answer (most likely this is IPv6 address on your network interface) :param source_port: Source UDP port in DNS answer (default: 53 - default port for DNS servers) :return: None """ while self.base.get_process_pid('tshark') != -1: kill(self.base.get_process_pid('tshark'), SIGINT) sleep(1) try: remove(RawDnsResolver.tshark_pcap_filename) except FileNotFoundError: pass tshark_command: str = 'tshark -i ' + self.network_interface + \ ' -f "ether dst ' + destination_mac_address + \ ' and ip dst ' + destination_ipv4_address + \ ' and udp src port ' + str(source_port) + \ '" -B 65535 -w ' + RawDnsResolver.tshark_pcap_filename + \ ' 1>/dev/null 2>&1' self.tshark_process = Popen(tshark_command, shell=True) sleep(0.5) while self.base.get_process_pid('tshark') == -1: input(self.base.c_warning + 'Start tshark: ' + self.base.info_text(tshark_command) + ' and press Enter to continue ...') sleep(1) # endregion # region Check tshark def _sniff_check(self): while True: try: assert isfile(RawDnsResolver.tshark_pcap_filename ), 'Tshark pcap file not found!' packets = rdpcap(RawDnsResolver.tshark_pcap_filename) for packet in packets: self._parse_packet(packet) except ValueError: pass except AssertionError: pass sleep(1) # endregion # region Stop tshark def _sniff_stop(self): while self.base.get_process_pid('tshark') != -1: kill(self.base.get_process_pid('tshark'), SIGTERM) sleep(1) try: packets = rdpcap(RawDnsResolver.tshark_pcap_filename) for packet in packets: self._parse_packet(packet) except ValueError: pass # endregion # region Send DNS queries to IPv4 NS server def _send_ipv4_queries(self, source_mac_address: str, source_ipv4_address: str, ns_server_mac_address: str, ns_server_ipv4_address: str, ns_server_port: int, queries: List[Dict[str, Union[int, str]]], send_socket: socket) -> None: """ Send DNS queries to IPv4 DNS servers :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface) :param source_ipv4_address: Source IPv4 address for DNS query (most likely this is IPv4 address on your network interface) :param ns_server_mac_address: DNS server MAC address for DNS query :param ns_server_ipv4_address: DNS server IPv4 address for DNS query :param ns_server_port: DNS server destination UDP port for DNS query (default: 53) :param queries: List of DNS queries for sending (example: [{'type': 1, 'class': 1, 'name': 'www.test.com'}]) :param send_socket: Raw socket for sending DNS queries :return: None """ for query in queries: # Set source UDP port and DNS transaction ID for sending DNS query udp_source_port: int = randint(2049, 65535) dns_transaction_id: int = randint(1, 65535) send_socket.send( self.dns.make_ipv4_request_packet( ethernet_src_mac=source_mac_address, ethernet_dst_mac=ns_server_mac_address, ip_src=source_ipv4_address, ip_dst=ns_server_ipv4_address, udp_src_port=udp_source_port, udp_dst_port=ns_server_port, transaction_id=dns_transaction_id, queries=[query])) # self.index_of_dns_query += 1 # current_percent_of_complete = int((self.index_of_dns_query / self.number_of_dns_queries) * 100) # if current_percent_of_complete > self.percent_of_complete: # self.percent_of_complete = current_percent_of_complete # stdout.write('\r') # stdout.write(self.base.c_info + 'Domain: ' + self.domain + # ' resolve percentage: ' + self.base.info_text(str(self.percent_of_complete) + '%')) # stdout.flush() # sleep(0.01) # endregion # region Send DNS queries to IPv6 NS server def _send_ipv6_queries(self, source_mac_address: str, source_ipv6_address: str, ns_server_mac_address: str, ns_server_ipv6_address: str, ns_server_port: int, queries: List[Dict[str, Union[int, str]]], send_socket: socket) -> None: """ Send DNS queries to IPv6 DNS servers :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface) :param source_ipv6_address: Source IPv6 address for DNS query (most likely this is IPv6 address on your network interface) :param ns_server_mac_address: DNS server MAC address for DNS query :param ns_server_ipv6_address: DNS server IPv6 address for DNS query :param ns_server_port: DNS server destination UDP port for DNS query (default: 53) :param queries: List of DNS queries for sending (example: [{'type': 1, 'class': 1, 'name': 'www.test.com'}]) :param send_socket: Raw socket for sending DNS queries :return: None """ for query in queries: # Set source UDP port and DNS transaction ID for sending DNS query udp_source_port: int = randint(2049, 65535) dns_transaction_id: int = randint(1, 65535) send_socket.send( self.dns.make_ipv6_request_packet( ethernet_src_mac=source_mac_address, ethernet_dst_mac=ns_server_mac_address, ip_src=source_ipv6_address, ip_dst=ns_server_ipv6_address, udp_src_port=udp_source_port, udp_dst_port=ns_server_port, transaction_id=dns_transaction_id, queries=[query])) # self.index_of_dns_query += 1 # current_percent_of_complete = int((self.index_of_dns_query / self.number_of_dns_queries) * 100) # if current_percent_of_complete > self.percent_of_complete: # self.percent_of_complete = current_percent_of_complete # stdout.write('\r') # stdout.write(self.base.c_info + 'DNS resolve percentage: ' + # self.base.info_text(str(self.percent_of_complete) + '%') + # ' length of results: ' + self.base.info_text(str(len(self.results)))) # stdout.flush() # sleep(0.01) # endregion # region Send DNS queries function def _send_queries(self, send_socket: socket, source_mac_address: str, source_ipv4_address: str, source_ipv6_address: str, domain: str, ns_servers: List[Dict[str, str]], destination_port: int = 53, max_threats_count: int = 9, subdomains: List[str] = ['www'], queries_type: List[int] = [1, 28], queries_class: List[int] = [1]) -> None: """ Send DNS queries to IPv4/IPv6 DNS servers :param send_socket: Raw socket for sending DNS queries :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface) :param source_ipv4_address: Source IPv4 address for DNS query (most likely this is IPv4 address on your network interface) :param source_ipv6_address: Source IPv6 address for DNS query (most likely this is IPv6 address on your network interface) :param domain: Target domain (example: 'test.com') :param ns_servers: List of DNS servers (example: [{'IPv4 address': '8.8.8.8', 'MAC address': '01:23:45:67:89:0a'}]) :param destination_port: UDP destination port (default: 53) :param max_threats_count: Maximum threats count (default: 9) :param subdomains: List of subdomains (default: ['www']) :param queries_type: List of queries type (default: [1, 28]; type 1: A, type 28: AAAA) :param queries_class: List of queries class (default: [1]; class 1: IN) :return: None """ # DNS query type: 1 (A) # DNS query type: 28 (AAAA) # DNS query class: 1 (IN) # region Init threat manager send_threats: ThreadManager = ThreadManager(max_threats_count) # endregion # region Make DNS queries list queries: List[Dict[str, Union[int, str]]] = list() for subdomain in subdomains: for query_type in queries_type: for query_class in queries_class: queries.append({ 'type': query_type, 'class': query_class, 'name': subdomain + '.' + domain }) # endregion # region Calculate number of DNS queries for one threat queries_len: int = len(queries) self.number_of_dns_queries = queries_len * len(ns_servers) ipv4_ns_servers_len: int = 0 ipv6_ns_servers_len: int = 0 for ns_server in ns_servers: if 'IPv4 address' in ns_server.keys(): ipv4_ns_servers_len += 1 if 'IPv6 address' in ns_server.keys(): ipv6_ns_servers_len += 1 if source_ipv6_address is not None: queries_len_for_threat = int( (queries_len * (ipv4_ns_servers_len + ipv6_ns_servers_len)) / max_threats_count) + 1 else: queries_len_for_threat = int( (queries_len * ipv4_ns_servers_len) / max_threats_count) + 1 # endregion # region Send DNS queries # region Send DNS queries to IPv4 NS servers for ns_server in ns_servers: if 'IPv4 address' in ns_server.keys(): for query_index in range(0, queries_len, queries_len_for_threat): send_threats.add_task( self._send_ipv4_queries, source_mac_address, source_ipv4_address, ns_server['MAC address'], ns_server['IPv4 address'], destination_port, queries[query_index:query_index + queries_len_for_threat], send_socket) # endregion # region Send DNS queries to IPv6 NS servers if source_ipv6_address is not None: for ns_server in ns_servers: if 'IPv6 address' in ns_server.keys(): for query_index in range(0, queries_len, queries_len_for_threat): send_threats.add_task( self._send_ipv6_queries, source_mac_address, source_ipv6_address, ns_server['MAC address'], ns_server['IPv6 address'], destination_port, queries[query_index:query_index + queries_len_for_threat], send_socket) # endregion # endregion # region Wait all threats send_threats.wait_for_completion() # endregion # endregion # region Main function: resolve def resolve(self, ns_servers: List[Dict[str, str]] = [{ 'IPv4 address': '8.8.8.8', 'MAC address': '01:23:45:67:89:0a' }], domain: str = 'google.com', subdomains_list: List[str] = ['www', 'mail', 'ns', 'test'], subdomains_file: Union[None, str] = None, subdomains_brute: bool = False, max_threats_count: int = 10, udp_destination_port: int = 53, timeout: int = 30) -> List[Dict[str, str]]: """ DNS resolve all subdomains in target domain :param ns_servers: List of DNS servers (example: [{'IPv4 address': '8.8.8.8', 'MAC address': '01:23:45:67:89:0a'}]) :param domain: Target domain (example: 'test.com') :param subdomains_list: List of subdomains (example: ['www','ns','mail']) :param subdomains_file: Name of file with subdomains (default: None) :param subdomains_brute: Brute mode on (auto make list with subdomains) if True, Brute mode off if False (default: False) :param max_threats_count: Maximum threats count (default: 10) :param udp_destination_port: UDP destination port (default: 53) :param timeout: Connection after send all DNS queries (default: 30) :return: List of dictionary (example: [{'Domain': 'www.test.com', 'IPv4 address': '1.2.3.4', 'IPv6 address': '-'}]) """ try: # region Clear results list self.index_of_dns_query = 0 self.results.clear() self.uniq_hosts.clear() # endregion # region Set target domain assert not (domain == ''), \ 'Target domain is empty, please set target domain in this parameter: ' + self.base.info_text('domain') self.domain = domain # endregion # region Subdomains list if len(subdomains_list) > 0: self.subdomains = subdomains_list # endregion # region Subdomains file if subdomains_file is not None: assert isfile(subdomains_file), \ 'File with subdomain list:' + self.base.error_text(subdomains_file) + ' not found!' with open(subdomains_file) as subdomains_file_descriptor: for subdomain in subdomains_file_descriptor.read( ).splitlines(): self.subdomains.append(subdomain) # endregion # region Subdomains brute if subdomains_brute: if not self.quiet: self.base.print_info( 'Make subdomains list for brute .... ') for character1 in RawDnsResolver.available_characters: self.subdomains.append(character1) for character2 in RawDnsResolver.available_characters: self.subdomains.append(character1 + character2) for character3 in RawDnsResolver.available_characters: self.subdomains.append(character1 + character2 + character3) # endregion # region Check length of subdomains list assert len(self.subdomains) != 0, \ 'List containing subdomains is empty, please set any of this parameters: ' \ + self.base.info_text('subdomain_list') + ' or ' \ + self.base.info_text('subdomain_file') + ' or ' \ + self.base.info_text('subdomain_brute') # endregion # region Create raw socket raw_socket: socket = socket(AF_PACKET, SOCK_RAW) raw_socket.bind((self.network_interface, 0)) # endregion # region Truncate temporary results file temporary_results_file = open( RawDnsResolver.temporary_results_filename, 'r+') temporary_results_file.truncate() temporary_results_file.close() # endregion # region Sniff DNS answers if not self.quiet: self.base.print_info('Start DNS answers sniffer for domain: ', self.domain) threats: ThreadManager = ThreadManager(max_threats_count) self._sniff_start(self.your_mac_address, self.your_ipv4_address, self.your_ipv6_address, udp_destination_port) threats.add_task(self._sniff_check) # endregion # region Send DNS queries if not self.quiet: self.base.print_info('Start sending DNS queries, time: ', str(datetime.now())) self._send_queries(send_socket=raw_socket, source_mac_address=self.your_mac_address, source_ipv4_address=self.your_ipv4_address, source_ipv6_address=self.your_ipv6_address, domain=domain, ns_servers=ns_servers, destination_port=udp_destination_port, max_threats_count=int(max_threats_count) - 1, subdomains=self.subdomains) # endregion # region Timeout if not self.quiet: self.base.print_info('Wait timeout: ', str(timeout) + ' sec') sleep(timeout) # endregion # region Return results self._sniff_stop() if not self.quiet: if len(self.results) > 0: self.base.print_success( 'Found ', str(len(self.results)), ' subdomains and addresses for domain: ', self.domain) else: self.base.print_error('Not found subdomains in domain: ', self.domain) return self.results # endregion except AssertionError as Error: self.base.print_error(Error.args[0]) exit(1) # endregion # region Get NS server of domain def get_name_servers(self, ipv4_gateway_mac: str = '01:23:45:67:89:0a', ipv6_gateway_mac: str = '01:23:45:67:89:0b', domain: str = 'google.com') -> List[Dict[str, str]]: """ Get NS servers of domain :param ipv4_gateway_mac: MAC address of IPv4 gateway (example: '01:23:45:67:89:0a') :param ipv6_gateway_mac: MAC address of IPv6 gateway (example: '01:23:45:67:89:0b') :param domain: Target domain (example: 'google.com') :return: List of IP addresses (example: ['216.239.34.10', '216.239.36.10', '216.239.32.10', '216.239.38.10']) """ # region Clear results list ns_servers: List[Dict[str, str]] = list() self.results.clear() # endregion # region Start sniffer if not self.quiet: self.base.print_info('Get NS records of domain: ' + domain + ' ...') self._sniff_start(self.your_mac_address, self.your_ipv4_address, self.your_ipv6_address, 53) # endregion # region Send DNS queries raw_socket: socket = socket(AF_PACKET, SOCK_RAW) raw_socket.bind((self.network_interface, 0)) name_servers_addresses = self.base.get_system_name_servers() for name_server_address in name_servers_addresses: if self.base.ip_address_validation(name_server_address): if self.base.ip_address_in_network(name_server_address, self.your_ipv4_network): name_server_mac: str = self.arp_scan.get_mac_address( self.network_interface, name_server_address) else: name_server_mac: str = ipv4_gateway_mac dns_query = self.dns.make_ns_query( ethernet_src_mac=self.your_mac_address, ethernet_dst_mac=name_server_mac, ip_src=self.your_ipv4_address, ip_dst=name_server_address, udp_src_port=randint(2049, 65535), udp_dst_port=53, transaction_id=randint(1, 65535), name=domain) raw_socket.send(dns_query) # endregion # region Resolve NS servers sleep(5) self._sniff_stop() ns_servers_names: List[str] = list() ns_servers_addresses: List[str] = list() for ns_server in self.results: ns_servers_names.append(ns_server['NS']) for ns_server_name in ns_servers_names: try: ns_server_addresses = gethostbyname_ex(ns_server_name) if len(ns_server_addresses) > 0: for ns_server_address in ns_server_addresses[2]: if ns_server_address not in ns_servers_addresses: ns_servers_addresses.append(ns_server_address) except herror: pass for ns_server_address in ns_servers_addresses: if self.base.ip_address_validation(ns_server_address): ns_servers.append({ 'IPv4 address': ns_server_address, 'MAC address': ipv4_gateway_mac }) if self.base.ipv6_address_validation(ns_server_address): ns_servers.append({ 'IPv6 address': ns_server_address, 'MAC address': ipv6_gateway_mac }) return ns_servers
# endregion # region Authorship information __author__ = 'Vladimir Ivanov' __copyright__ = 'Copyright 2019, Raw-packet Project' __credits__ = [''] __license__ = 'MIT' __version__ = '0.0.4' __maintainer__ = 'Vladimir Ivanov' __email__ = '*****@*****.**' __status__ = 'Production' # endregion # region Check user and platform Base = Base() ArpScan = ArpScan() Sniff = Sniff_raw() TM = ThreadManager(2) Base.check_user() Base.check_platform() # endregion # region Parse script arguments parser = ArgumentParser(description='Network conflict creator script') parser.add_argument('-i', '--interface', type=str, help='Set interface name for listen and send packets') parser.add_argument('-t', '--target_ip', type=str, help='Set target IP address', default=None) parser.add_argument('-m', '--target_mac', type=str, help='Set target MAC address', default=None) parser.add_argument('--replies', action='store_true', help='Send only ARP replies')
def scan( self, interface: Union[None, str] = None, timeout: int = 5, retry: int = 5, mqtt_client=None, ): self.base.print_info('[scanner]: starting') try: net_interface = str = \ self.base.network_interface_selection( interface_name=interface, message='Please select a network interface' ) net_interface_settings: Dict[str, Union[None, str, List[str]]] = \ self.base.get_interface_settings( interface_name = net_interface, required_parameters = [ 'mac-address', 'ipv4-address', 'first-ipv4-address', 'last-ipv4-address', ] ) self.base.print_info(f'[scanner]: interface -> %s' % net_interface_settings['network-interface']) self.base.print_info(f'[scanner]: this IP -> %s' % net_interface_settings['ipv4-address']) self.base.print_info(f'[scanner]: this MAC -> %s' % net_interface_settings['mac-address']) arp_scanner: ArpScan = ArpScan(network_interface=net_interface) results: List[Dict[str, str]] = arp_scanner.scan( timeout, retry, target_ip_address=None, check_vendor=True, exclude_ip_addresses=net_interface_settings['ipv4-address'], exit_on_failure=True, show_scan_percentage=True, ) assert len(results) != 0, 'no devices found' if (self.mode == 'all'): pretty_table = PrettyTable([ self.base.cINFO + 'IP' + self.base.cEND, self.base.cINFO + 'MAC' + self.base.cEND, self.base.cINFO + 'vendor' + self.base.cEND ]) self.base.print_info('[scanner]: found devices: ') for result in results: device = { 'mac': result['mac-address'], 'ip': result['ip-address'], 'vendor': result['vendor'], } pretty_table.add_row( [device['ip'], device['mac'], device['vendor']]) print(pretty_table) if (mqtt_client is not None): self.base.print_info( '[scanner]: sending presence data to MQTT broker...') for device in results: payload = { 'ip': device['ip-address'], 'mac': device['mac-address'], 'vendor': device['vendor'], 'last_seen': datetime.now().strftime('%Y-%m-%d %H:%M:%S') } mqtt_client.client.loop() mqtt_client.send(json.dumps(payload)) else: self.base.print_warning( '[scanner]: no MQTT client; won\'t report anything') elif (self.mode == 'targets'): pretty_table = PrettyTable([ self.base.cINFO + 'IP' + self.base.cEND, self.base.cINFO + 'MAC' + self.base.cEND, self.base.cINFO + 'vendor' + self.base.cEND, self.base.cINFO + 'name' + self.base.cEND ]) targets = list( map( lambda target: { 'mac': target['mac'], 'name': target['identifier'], }, self.config['targets'])) found_targets = [] if (len(results) < 1): self.base.print_warning('[scanner]: no devices found') return for result in results: found_target = [ \ target for target in targets if target['mac'] == result['mac-address'] ] if (len(found_target) > 0): found_target = \ { 'mac': result['mac-address'], 'name': found_target[0]['name'], 'ip': result['ip-address'], 'vendor': result['vendor'], } found_targets.append(found_target) pretty_table.add_row([ found_target['ip'], found_target['mac'], found_target['vendor'], found_target['name'] ]) if (len(found_targets) > 0): self.base.print_info('[scanner]: targets found: ') print(pretty_table) if (mqtt_client is not None): self.base.print_info( '[scanner]: sending presence data to MQTT broker...' ) for target in found_targets: payload = { 'name': target['name'], 'ip': target['ip'], 'mac': target['mac'], 'vendor': target['vendor'], 'last_seen': datetime.now().strftime('%Y-%m-%d %H:%M:%S') } mqtt_client.client.loop() mqtt_client.send(json.dumps(payload)) else: self.base.print_warning( '[scanner]: no MQTT client; won\'t report anything' ) else: self.base.print_warning('[scanner]: no targets found') except Exception as e: self.base.print_error(f'[scanner]: exception -> %s' % e)
def set_ipv4_target(self, network_interface: str, target_ipv4_address: Union[None, str] = None, target_mac_address: Union[None, str] = None, target_vendor: Union[None, str] = None, target_ipv4_address_required: bool = False, exclude_ipv4_addresses: List[str] = [], quiet: bool = False) -> Dict[str, str]: # region Variables target: Dict[str, str] = { 'mac-address': None, 'ipv4-address': None, 'vendor': None } arp_scan: ArpScan = ArpScan(network_interface=network_interface) # endregion # region Target IPv4 address is Set if target_ipv4_address is not None: target['ipv4-address'] = self.check_ipv4_address( network_interface=network_interface, ipv4_address=target_ipv4_address, parameter_name='target IPv4 address', is_local_ipv4_address=True) # endregion # region Target IPv4 address not Set else: assert not target_ipv4_address_required, 'Please set target IPv4 address!' if not quiet: self._base.print_info('Start ARP scan ...') results: List[Dict[str, str]] = arp_scan.scan( timeout=3, retry=3, target_ip_address=None, check_vendor=True, exclude_ip_addresses=exclude_ipv4_addresses, exit_on_failure=True, show_scan_percentage=not quiet) if target_mac_address is not None: target['mac-address'] = self.check_mac_address( mac_address=target_mac_address, parameter_name='target MAC address') for result in results: if result['mac-address'] == target['mac-address']: target['ipv4-address'] = result['ip-address'] target['vendor'] = result['vendor'] break assert target['ipv4-address'] is not None, \ 'Could no found alive host with MAC address: ' + self._base.error_text(target['mac-address']) return target if target_vendor is not None: results_with_vendor: List[Dict[str, str]] = list() for result in results: if search(target_vendor, result['vendor'], IGNORECASE): results_with_vendor.append(result) results = results_with_vendor assert len(results) != 0, \ 'Could not found alive hosts on interface: ' + self._base.error_text(network_interface) if len(results) == 1: target['ipv4-address'] = results[0]['ip-address'] target['mac-address'] = results[0]['mac-address'] target['vendor'] = results[0]['vendor'] return target else: if target_vendor is not None: self._base.print_success( 'Found ', str(len(results)), ' ' + target_vendor.capitalize() + ' devices on interface: ', network_interface) else: self._base.print_success('Found ', str(len(results)), ' alive hosts on interface: ', network_interface) hosts_pretty_table: PrettyTable = PrettyTable([ self._base.cINFO + 'Index' + self._base.cEND, self._base.cINFO + 'IPv4 address' + self._base.cEND, self._base.cINFO + 'MAC address' + self._base.cEND, self._base.cINFO + 'Vendor' + self._base.cEND ]) device_index: int = 1 for device in results: hosts_pretty_table.add_row([ str(device_index), device['ip-address'], device['mac-address'], device['vendor'] ]) device_index += 1 print(hosts_pretty_table) device_index -= 1 print(self._base.c_info + 'Select target from range (1-' + str(device_index) + '): ', end='') current_device_index = input() if not current_device_index.isdigit(): self._base.print_error('Your input data: ' + str(current_device_index) + ' is not digit!') exit(1) if any([ int(current_device_index) < 1, int(current_device_index) > device_index ]): self._base.print_error( 'Your number is not within range (1-' + str(device_index) + ')') exit(1) current_device_index = int(current_device_index) - 1 device: Dict[str, str] = results[current_device_index] target['ipv4-address'] = device['ip-address'] target['mac-address'] = device['mac-address'] target['vendor'] = device['vendor'] self._base.print_info( 'Your choose target: ', target['ipv4-address'] + ' (' + target['mac-address'] + ')') return target # endregion # region Target MAC address not Set if target_mac_address is None: self._base.print_info( 'Find MAC address of device with IP address: ', target['ipv4-address'], ' ...') target['mac-address'] = arp_scan.get_mac_address( target_ip_address=target['ipv4-address'], exit_on_failure=True, show_scan_percentage=False) # endregion # region Target MAC address is Set else: target['mac-address'] = self.check_mac_address( mac_address=target_mac_address, parameter_name='target MAC address') # endregion # region Return target return target