Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the PSRP protocol for powershell commands #169

Closed
mwrock opened this issue Jan 6, 2016 · 8 comments
Closed

Use the PSRP protocol for powershell commands #169

mwrock opened this issue Jan 6, 2016 · 8 comments

Comments

@mwrock
Copy link
Member

mwrock commented Jan 6, 2016

Currently we run powershell commands by spawning powershell.exe from winrm's cmd.exe. This seems to be a universal cross platform windows remote execution pattern implemented in many languages.

However, there is another protocol psrp that "piggy backs" on top of the same SOAP based wsman wire protocol as winrm. This creates a powershell shell and removes the 8k character limit in cmd.exe. It also allows us to avoid -enconedCommand which is currently not suppoerted on windows nano server.

First, I don't think we want to create a separate repo for this. Mainly because we dont need a "complete" implementation with full serialization/deserialization of clixml. Also, ideally we could run powershell through this protocol with this gem in a completely transparent way.

I have spiked/hacked out a very basic working example of opening a psrp shell, sending a command and receiving a response. It should never see the light of day but illustrates how we can get this to work. This can be found in this branch.

I plan to create a PR based on this spike but cleaned up/refactored.

cc @smurawski @carpnick @adamedx @ksubrama @btm @jaym @chefsalim

@mwrock
Copy link
Member Author

mwrock commented Jan 6, 2016

Here are some notes on how to approach "folding" this into this gem.

Partial implementation

In my opinion, the complete psrp spec is way more complicated than what is needed for basic "shell out" style (send text command and get text response) invocation. I could see a separat gem providing more complete implementation. There are some cool things one could do with the command-metadata requests and clixml responses:

  • Create a cross platform tab completing repl
  • deserialize clixml reponses into dynamic ruby classes

I propose issuing all commands like so:

Invoke-Expression -Command #{input_command} | Out-String

This does have to be sent in clixml format but we can "boiler plate" that as I did in the psrp branch and simply interpolate the given command to run. The out-string allows the response to come back in string format and not as a huge cli-xml response. We'd have to do some parsing/decoding but it would be much more straight forward that parsing the entire clixml response.

There is some base64 encoding/decoding we'd want to do to eliminate quoting hell but that can be worked out.

CommandExecutor subclasses

My spike was branched from the executor branch in pr #167 . That pr (which still stands and is not blocked by this) has a single CommandExecutor with different methods for cmd and powershell invocations. I think we should have a CmdExecutor and PowershellExecutor. Most of the code can still use the same base.

@sneal
Copy link
Member

sneal commented Jan 6, 2016

Implementing a partial psrp support in the winrm gem seems like the right thing to do for now.

Sorry for the pun, but you @mwrock!

@pecigonzalo
Copy link

Fantastic @mwrock , i agree it can be done with a fairly smaller implementation, as i was working on a similar thing for the go implementation by running MITM on a powershell remote session and reflecting from that. Would you like me to put here the output of that?

@mwrock
Copy link
Member Author

mwrock commented Jan 12, 2016

Thanks @pecigonzalo I think we both probably took a similar approach. I created my spike by studying wireshark traces of remote powershell sessions and cross referencing the psrp spec. Looking forward to the day when I never have to look at XML again not to mention XML primarily filled with Base64 encoded binary data. Alas, I may have a ways to wait :)

@pecigonzalo
Copy link

Apparently OpenSSH is on the way for MS so we can dream!
Another tip is to reflect: C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll with dotPeek or something, altough the implementation look complicated there.
Particularly - > System.Manageent.Automation.Remoting.Client -> WSManClientSssionTransportManager

@mwrock
Copy link
Member Author

mwrock commented Jan 12, 2016

haha. Yeah I looked quite a bit at that too. Some of the binary serialization would have been easier in C# than ruby. Particularly converting GUIDs to byte arrays.

@zenchild
Copy link
Member

This is sweet @mwrock. Nice work.

@mwrock
Copy link
Member Author

mwrock commented Jan 12, 2016

Cant wait to see it work "for reals"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants