Exemple #1
0
    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)
Exemple #3
0
    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
Exemple #4
0
        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
Exemple #5
0
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)
Exemple #6
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
Exemple #7
0
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)
Exemple #8
0
__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,
Exemple #9
0
# 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])
Exemple #10
0
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
Exemple #11
0
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)
Exemple #12
0
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)
Exemple #13
0
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
Exemple #14
0
# 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')
Exemple #15
0
    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)
Exemple #16
0
    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