def _scan_handler(self, args): """ Handles 'scan' command-line argument (Re)scans for hosts on the network """ if args.iprange: try: if '-' in args.iprange: iprange = list( netaddr.iter_iprange(*args.iprange.split('-'))) else: iprange = list(netaddr.IPNetwork(args.iprange)) except netaddr.core.AddrFormatError: IO.error('ip range invalid.') return else: iprange = None for host in self.hosts: self._free_host(host) IO.spacer() self.hosts = self.host_scanner.scan(iprange) IO.ok('{}{}{} hosts discovered.'.format(IO.Fore.LIGHTYELLOW_EX, len(self.hosts), IO.Style.RESET_ALL)) IO.spacer()
def _hosts_handler(self, args): """ Handles 'hosts' command-line argument Displays discovered hosts """ table_data = [[ '{}ID{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}IP address{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}MAC address{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}Hostname{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}Status{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL) ]] with self.hosts_lock: for host in self.hosts: table_data.append([ '{}{}{}'.format(IO.Fore.LIGHTYELLOW_EX, self._get_host_id(host, lock=False), IO.Style.RESET_ALL), host.ip, host.mac, host.name, host.pretty_status() ]) table = SingleTable(table_data, 'Hosts') if not args.force and not table.ok: IO.error( 'table does not fit terminal. resize or decrease font size. you can also force the display (--force).' ) return IO.spacer() IO.print(table.table) IO.spacer()
def _hosts_handler(self, args): """ Handles 'hosts' command-line argument Displays discovered hosts """ table_data = [[ '{}ID{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}IP-Address{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}MAC-Address{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}Hostname{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}Status{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL) ]] for i, host in enumerate(self.hosts): table_data.append([ '{}{}{}'.format(IO.Fore.LIGHTYELLOW_EX, i, IO.Style.RESET_ALL), host.ip, host.mac, host.name if host.name is not None else '', host.pretty_status() ]) table = SingleTable(table_data, 'Hosts') if not table.ok: IO.error( 'table does not fit terminal. resize or decrease font size.') return IO.spacer() IO.print(table.table) IO.spacer()
def interrupt_handler(self): IO.spacer() IO.ok('cleaning up... stand by...') self.arp_spoofer.stop() for host in self.hosts: self._free_host(host)
def run(): """ Main entry point of the application """ version = get_version() args = parse_arguments() IO.initialize(args.colorless) IO.print(get_main_banner(version)) if not is_linux(): IO.error('run under linux.') return if not is_privileged(): IO.error('run as root.') return args = process_arguments(args) if args is None: return if initialize(args.interface): IO.spacer() menu = MainMenu(version, args.interface, args.gateway_ip, args.gateway_mac, args.netmask) menu.start() cleanup(args.interface)
def _scan_handler(self, args): """ Handles 'scan' command-line argument (Re)scans for hosts on the network """ if args.iprange: iprange = self._parse_iprange(args.iprange) if iprange is None: IO.error('invalid ip range.') return else: iprange = None with self.hosts_lock: for host in self.hosts: self._free_host(host) IO.spacer() IO.discord("Scanning...") hosts = self.host_scanner.scan(iprange) hosts = [host for host in hosts if host not in self.hosts] self.hosts_lock.acquire() self.hosts += hosts self.hosts_lock.release() IO.ok('{}{}{} hosts discovered.'.format(IO.Fore.LIGHTYELLOW_EX, len(hosts), IO.Style.RESET_ALL)) IO.spacer() IO.discord("{} hosts terdeteksi".format(len(hosts)))
def process_arguments(args): """ Processes the specified command-line arguments, adds them to a named tuple and returns. Executes actions specified in the command line, e.g. flush network settings """ if args.interface is None: interface = netutils.get_default_interface() if interface is None: IO.error('default interface could not be resolved. specify manually (-i).') return else: interface = args.interface if not netutils.exists_interface(interface): IO.error('interface {}{}{} does not exist.'.format(IO.Fore.LIGHTYELLOW_EX, interface, IO.Style.RESET_ALL)) return IO.ok('interface: {}{}{}'.format(IO.Fore.LIGHTYELLOW_EX, interface, IO.Style.RESET_ALL)) if args.gateway_ip is None: gateway_ip = netutils.get_default_gateway() if gateway_ip is None: IO.error('default gateway address could not be resolved. specify manually (-g).') return else: gateway_ip = args.gateway_ip IO.ok('gateway ip: {}{}{}'.format(IO.Fore.LIGHTYELLOW_EX, gateway_ip, IO.Style.RESET_ALL)) if args.gateway_mac is None: gateway_mac = netutils.get_mac_by_ip(interface, gateway_ip) if gateway_mac is None: IO.error('gateway mac address could not be resolved.') return else: if netutils.validate_mac_address(args.gateway_mac): gateway_mac = args.gateway_mac.lower() else: IO.error('gateway mac is invalid.') return IO.ok('gateway mac: {}{}{}'.format(IO.Fore.LIGHTYELLOW_EX, gateway_mac, IO.Style.RESET_ALL)) if args.netmask is None: netmask = netutils.get_default_netmask(interface) if netmask is None: IO.error('netmask could not be resolved. specify manually (-n).') return else: netmask = args.netmask IO.ok('netmask: {}{}{}'.format(IO.Fore.LIGHTYELLOW_EX, netmask, IO.Style.RESET_ALL)) if args.flush: netutils.flush_network_settings(interface) IO.spacer() IO.ok('flushed network settings') return InitialArguments(interface=interface, gateway_ip=gateway_ip, gateway_mac=gateway_mac, netmask=netmask)
def interrupt_handler(self, ctrl_c=True): if ctrl_c: IO.spacer() IO.ok('cleaning up... stand by...') self.arp_spoofer.stop() self.bandwidth_monitor.stop() for host in self.hosts: self._free_host(host)
def initialize(interface): """ Sets up requirements, e.g. IP-Forwarding, 3rd party applications """ if not netutils.create_qdisc_root(interface): IO.spacer() IO.error('qdisc root handle could not be created. maybe flush network settings (--flush).') return False if not netutils.enable_ip_forwarding(): IO.spacer() IO.error('ip forwarding could not be enabled.') return False return True
def _scan_handler(self, args): """ Handles 'scan' command-line argument (Re)scans for hosts on the network """ for host in self.hosts: self._free_host(host) IO.spacer() self.hosts = self.host_scanner.scan() IO.ok('{}{}{} hosts discovered.'.format(IO.Fore.LIGHTYELLOW_EX, len(self.hosts), IO.Style.RESET_ALL)) IO.spacer()
def _watch_handler(self, args): if len(args) == 0: watch_table_data = [[ '{}ID{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}IP address{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}MAC address{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL) ]] set_table_data = [[ '{}Attribute{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}Value{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL) ]] hist_table_data = [[ '{}ID{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}Old IP address{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}New IP address{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL), '{}Time{}'.format(IO.Style.BRIGHT, IO.Style.RESET_ALL) ]] iprange = self.host_watcher.iprange interval = self.host_watcher.interval set_table_data.append([ '{}range{}'.format(IO.Fore.LIGHTYELLOW_EX, IO.Style.RESET_ALL), '{} addresses'.format(len(iprange)) if iprange is not None else 'default' ]) set_table_data.append([ '{}interval{}'.format(IO.Fore.LIGHTYELLOW_EX, IO.Style.RESET_ALL), '{}s'.format(interval) ]) for host in self.host_watcher.hosts: watch_table_data.append([ '{}{}{}'.format(IO.Fore.LIGHTYELLOW_EX, self._get_host_id(host), IO.Style.RESET_ALL), host.ip, host.mac ]) for recon in self.host_watcher.log_list: hist_table_data.append([ recon['old'].mac, recon['old'].ip, recon['new'].ip, recon['time'] ]) watch_table = SingleTable(watch_table_data, "Watchlist") set_table = SingleTable(set_table_data, "Settings") hist_table = SingleTable(hist_table_data, 'Reconnection History') IO.spacer() IO.print(watch_table.table) IO.spacer() IO.print(set_table.table) IO.spacer() IO.print(hist_table.table) IO.spacer()
def _analyze_handler(self, args): hosts = self._get_hosts_by_ids(args.id) if hosts is None or len(hosts) == 0: IO.error('no hosts to be analyzed.') return duration = 30 # in s if args.duration: if not args.duration.isdigit(): IO.error('invalid duration.') return duration = int(args.duration) hosts_to_be_freed = set() host_values = {} for host in hosts: if not host.spoofed: hosts_to_be_freed.add(host) self.arp_spoofer.add(host) self.bandwidth_monitor.add(host) host_result = self.bandwidth_monitor.get(host) host_values[host] = {} host_values[host]['prev'] = (host_result.upload_total_size, host_result.download_total_size) IO.ok('analyzing traffic for {}s.'.format(duration)) time.sleep(duration) error_occurred = False for host in hosts: host_result = self.bandwidth_monitor.get(host) if host_result is None: # host reconnected during analysis IO.error('host reconnected during analysis.') error_occurred = True else: host_values[host]['current'] = ( host_result.upload_total_size, host_result.download_total_size) IO.ok('cleaning up...') for host in hosts_to_be_freed: self._free_host(host) if error_occurred: return upload_chart = BarChart(max_bar_length=29) download_chart = BarChart(max_bar_length=29) for host in hosts: upload_value = host_values[host]['current'][0] - host_values[host][ 'prev'][0] download_value = host_values[host]['current'][1] - host_values[ host]['prev'][1] prefix = '{}{}{} ({}, {})'.format(IO.Fore.LIGHTYELLOW_EX, self._get_host_id(host), IO.Style.RESET_ALL, host.ip, host.name) upload_chart.add_value(upload_value.value, prefix, upload_value) download_chart.add_value(download_value.value, prefix, download_value) upload_table = SingleTable([[upload_chart.get()]], 'Upload') download_table = SingleTable([[download_chart.get()]], 'Download') upload_table.inner_heading_row_border = False download_table.inner_heading_row_border = False IO.spacer() IO.print(upload_table.table) IO.print(download_table.table) IO.spacer()