[
  {
    "path": "CppWSManWinRM.cpp",
    "content": "/*\r\n\tCppWSManWinRM.cpp\r\n\r\n\t   Purpose: A simple POC for leveraging a WMI class to execute a remote command over the WinRM (WSMan) protocol using the WSMan.Automation COM object (wsmauto.dll)\r\n\t   Author: @bohops\r\n\t   License: BSD 3-Clause\r\n\r\n\t   Usage: CppWSManWinRM.exe [hostname] [command]\r\n\t   //Usage: CppWSManWinRM.exe [hostname] [command] [domain\\user] [password] <-- Does not work...yet\r\n\r\n\t   Example: CppWSManWinRM.exe host.domain.local notepad.exe\r\n\t   //Example: CppWSManWinRM.exe host.domain.local \"cmd /c notepad.exe\" domain\\joe.user P@ssw0rd <-- Does not work...yet\r\n\r\n\t   Link: http://forums.codeguru.com/showthread.php?499875-WSManAutomation-lib-is-missing (Primary Code Source -> credit: ssoma from CodeGuru forums)\r\n\t   Link: https://docs.microsoft.com/en-us/windows/win32/winrm/wsman\r\n*/\r\n\r\n#include <comdef.h>\r\n#include <windows.h>\r\n#include <wsmandisp.h>\r\n#include \"wsmandisp_i.c\"\r\n#include <iostream>\r\n\r\nusing namespace std;\r\n\r\nint ExecRemoteCmd(string host, string cmd, string user, string passwd);\r\n\r\nint main(int argc, char** argv)\r\n{\r\n\tif (argc == 3) //Args: 2 (+ 1)\r\n\t\tint res = ExecRemoteCmd(argv[1], argv[2], \"\", \"\");\r\n\telse if (argc == 5) //Args: 4 (+1)\r\n\t\tcout << \":-|\"; //int res = ExecRemoteCmd(argv[1], argv[2], argv[3], argv[4]); <--- not implemented....yet\r\n\telse\r\n\t{\r\n\t\tcout << \"Usage:   CppWSManWinRM.exe [hostname] [command]\" << endl;\r\n\t\tcout << \"Example: CppWSManWinRM.exe host.domain.local \\\"cmd /c notepad.exe\\\"\" << endl;\r\n\t\t//cout << \"  -or-\" << endl;\r\n\t\t//cout << \"Usage:   CppWSManWinRM.exe [hostname] [command] [domain\\\\user] [password]\" << endl;\r\n\t\t//cout << \"Example: CppWSManWinRM.exe host.domain.local \\\"cmd /c notepad.exe\\\" domain\\\\joe.user P@ssw0rd\" << endl;\r\n\t}\r\n}\r\nint ExecRemoteCmd(string host, string cmd, string user, string passwd)\r\n{\r\n\t_bstr_t protocol = \"http\";\r\n\t_bstr_t port = \"5985\";\r\n\r\n\t_bstr_t hostname = (_bstr_t)host.c_str();\r\n\t_bstr_t command = (_bstr_t)cmd.c_str();\r\n\t//_bstr_t username = (_bstr_t)user.c_str();\r\n\t//_bstr_t password = (_bstr_t)passwd.c_str();\r\n\r\n\tHRESULT hres = NULL;\r\n\tHRESULT hr = S_OK;\r\n\tIDispatch* pSvc = NULL;\r\n\tIDispatch* pOptions = NULL;\r\n\tIWSManSession* pSvc1 = NULL;\r\n\r\n\t// Initialize COM\r\n\thres = CoInitializeEx(0, COINIT_MULTITHREADED);\r\n\tif (FAILED(hres))\r\n\t{\r\n\t\tcout << \"Failed to initialize COM library. Error code = 0x\" << hex << hres << endl;\r\n\t\treturn 1; // Program has failed.\r\n\t}\r\n\r\n\t//Instatliate WSMAN COM Object\r\n\tIWSMan* pLoc = NULL;\r\n\thres = CoCreateInstance(CLSID_WSMan, 0, CLSCTX_INPROC_SERVER, IID_IWSMan, (LPVOID*)&pLoc);\r\n\tif (FAILED(hres))\r\n\t{\r\n\t\tcout << \"Failed to create IWSMan object.\" << \" Err code = 0x\" << hex << hres << endl;\r\n\t\tCoUninitialize();\r\n\t\treturn 1; // Program has failed.\r\n\t}\r\n\r\n\t//Create Remote Session\r\n\tcout << \"[*] Creating session with the remote system...\" << endl;\r\n\tpSvc = reinterpret_cast<IDispatch*>(pSvc1);\r\n\tlong f = 0;\r\n\r\n\t// This needs to be fixed for supplied credentials.  Pull requests welcome...\r\n\t//if (\"creds\")\r\n\t//{\r\n\t//\t//HRESULT SessionFlagUseNoAuthentication(f);\r\n\t//\tHRESULT SessionFlagCredUsernamePassword(f);\r\n\t//\tIWSManConnectionOptions* options = NULL;\r\n\t//\toptions->put_UserName(bstr_t(\"corp\\\\corpmin\"));\r\n\t//\toptions->put_Password(bstr_t(\"CorpM@ster\"));\r\n\t//\tpOptions = reinterpret_cast<IDispatch*>(options);\r\n\t//\thres = pLoc->CreateConnectionOptions(&pOptions);\r\n\t//\thres = pLoc->CreateSession(_bstr_t(\"http://corp-dc:5985/wsman\"), f, pOptions, &pSvc);\r\n\t//}\r\n\t//else\r\n\t//{\r\n\t//\thres = pLoc->CreateSession(_bstr_t(\"http://corp-dc:5985/wsman\"), 0, NULL, &pSvc);\r\n\t//}\r\n\r\n\thres = pLoc->CreateSession(protocol + _bstr_t(\"://\") + hostname + _bstr_t(\":\") + port + _bstr_t(\"/wsman\"), 0, NULL, &pSvc);\r\n\tif (FAILED(hres))\r\n\t{\r\n\t\tcout << \"Could not connect. Error code = 0x\" << hex << hres << endl;\r\n\t\tpLoc->Release();\r\n\t\tCoUninitialize();\r\n\t\treturn 1; // Program has failed.\r\n\t}\r\n\r\n\t//Invoke Command\r\n\tcout << \"[*] Connected to the remote WinRM system\" << endl;\r\n\tpSvc1 = reinterpret_cast<IWSManSession*>(pSvc);\r\n\t_variant_t resource = \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\";\r\n\t_bstr_t parameters = \"<p:Create_INPUT xmlns:p=\\\"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\\\"><p:CommandLine>\" + command + \"</p:CommandLine></p:Create_INPUT>\";\r\n\twchar_t* response = new wchar_t(1000);\r\n\thres = pSvc1->Invoke(_bstr_t(\"Create\"), resource, parameters, 0, &response);\r\n\r\n\t//Print Response \r\n\tcout << \"[*] Result Code: \" << response;\r\n\r\n\t//Cleanup\r\n\tpSvc->Release();\r\n\tpSvc1->Release();\r\n\tpOptions->Release();\r\n\tpLoc->Release();\r\n\tCoUninitialize();\r\n\r\n\treturn 0;\r\n}"
  },
  {
    "path": "LICENSE",
    "content": "BSD 3-Clause License\n\nCopyright (c) 2020, bohops\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its\n   contributors may be used to endorse or promote products derived from\n   this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# WSMan-WinRM\nA collection of proof-of-concept source code and scripts for executing remote commands over WinRM using the WSMan.Automation COM object. \n\n## Background\nFor background information, please refer to the following blog post: [WS-Management COM: Another Approach for WinRM Lateral Movement](https://bohops.com/2020/05/12/ws-management-com-another-approach-for-winrm-lateral-movement/)\n\n## Notes\n- SharpWSManWinRM.cs and CppWsManWinRM.cpp compile in Visual Studio 2019.  Refer to the code comments for required imports/references/etc.\n- All examples leverage the WMI Win32_Process class and WMI Create method for invocation. \n\n## Usage\n\n### SharpWSManWinRM.cs\n```\n Usage: SharpWSManWinRM.exe <hostname> <command>\n Usage: SharpWSManWinRM.exe <hostname> <command> <domain\\user> <password>\n\n Example: SharpWSManWinRM.exe host.domain.local notepad.exe\n Example: SharpWSManWinRM.exe host.domain.local \"cmd /c notepad.exe\" domain\\joe.user P@ssw0rd\n```\n### WSManWinRM.ps1\n```\n Usage: Invoke-WSManWinRM -hostname <hostname> -command <command>\n Usage: Invoke-WSManWinRM -hostname <hostname> -command <command> -user <domain\\user> -password <password>\n\n Example: import-module .\\WSManWinRM.ps1\n          Invoke-WSManWinRM -hostname MyServer.domain.local -command calc.exe\n Example: import-module .\\WSManWinRM.ps1\n          Invoke-WSManWinRM -hostname MyServer.domain.local -command calc.exe -user domain\\joe.user -password P@ssw0rd\n```\t\t  \n\t\t  \n### WSManWinRM.vbs\n```\n Usage: cscript.exe SharpWSManWinRM.vbs <hostname> <command>\n Usage: cscript.exe SharpWSManWinRM.vbs <hostname> <command> <domain\\user> <password>\n\n Example: cscript.exe SharpWSManWinRM.vbs host.domain.local notepad.exe\n Example: cscript.exe SharpWSManWinRM.vbs host.domain.local \"cmd /c notepad.exe\" domain\\joe.user P@ssw0rd\t\n```\n### WSManWinRM.js\n```\n Usage: cscript.exe SharpWSManWinRM.js <hostname> <command>\n Usage: cscript.exe SharpWSManWinRM.js <hostname> <command> <domain\\user> <password>\n\n Example: cscript.exe SharpWSManWinRM.js host.domain.local notepad.exe\n Example: cscript.exe SharpWSManWinRM.js host.domain.local \"cmd /c notepad.exe\" domain\\joe.user P@ssw0rd\t \n```\n### CppWSManWinRM.cpp\n```\n Usage: CppWSManWinRM.exe <hostname> <command>\n\n Example: CppWSManWinRM.exe host.domain.local notepad.exe\n \n Note: Username/password option does not work yet\n ```\n \n## Ethics\n\nWSMan-WinRM is designed to help security professionals perform ethical and legal security assessments and penetration tests. Do not use for nefarious purposes.\n\n"
  },
  {
    "path": "SharpWSManWinRM.cs",
    "content": "﻿/*\r\n    SharpWSManWinRM.cs\r\n\r\n       Purpose: A simple POC for leveraging a WMI class to execute a remote command over the WinRM (WSMan) protocol using the WSMan.Automation COM object (wsmauto.dll)\r\n       Author: @bohops\r\n       License: BSD 3-Clause\r\n\r\n       Usage: SharpWSManWinRM.exe [hostname] [command]\r\n       Usage: SharpWSManWinRM.exe [hostname] [command] [domain\\user] [password]\r\n\r\n       Example: SharpWSManWinRM.exe host.domain.local notepad.exe\r\n       Example: SharpWSManWinRM.exe host.domain.local \"cmd /c notepad.exe\" domain\\joe.user P@ssw0rd\r\n\r\n       Link: https://docs.microsoft.com/en-us/windows/win32/winrm/wsman\r\n*/\r\n\r\nusing System;\r\nusing System.Runtime.InteropServices;\r\nusing System.Xml;\r\nusing WSManAutomation;  //Add Reference -> windows\\system32\\wsmauto.dll (or COM: Microsoft WSMan Automation V 1.0 Library)\r\n\r\nnamespace SharpWinRM\r\n{\r\n    //Globals vars to store protocol/port info for now before testing out TLS/SSL\r\n    public class Globals\r\n    {\r\n        public const string protocol = \"http\";\r\n        public const string port = \"5985\";\r\n    }\r\n    class Program\r\n    {\r\n        static void Main(string[] args)\r\n        {\r\n            if (args.Length == 2)\r\n                ExecRemoteCmd(args[0], args[1], \"\", \"\");\r\n            else if (args.Length == 4)\r\n                ExecRemoteCmd(args[0], args[1], args[2], args[3]);\r\n            else\r\n            {\r\n                Console.WriteLine(\"Usage:   SharpWSManWinRM.exe [hostname] [command]\\n\" +\r\n                                  \"Example: SharpWSManWinRM.exe host.domain.local \\\"cmd /c notepad.exe\\\"\");\r\n                Console.WriteLine(\"\\n    -or-\\n\");\r\n                Console.WriteLine(\"Usage:   SharpWSManWinRM.exe [hostname] [command] [domain\\\\user] [password]\\n\" +\r\n                                  \"Example: SharpWSManWinRM.exe host.domain.local \\\"cmd /c notepad.exe\\\" domain\\\\joe.user P@ssw0rd\");\r\n            }\r\n        }\r\n\r\n        static void ExecRemoteCmd(string host, string cmd, string user, string password)\r\n        {\r\n            try\r\n            {\r\n                //Setup session & execute remote command\r\n                IWSManEx wsman = new WSMan();\r\n                IWSManConnectionOptions options = (IWSManConnectionOptions)wsman.CreateConnectionOptions();\r\n                string sessionUrl = Globals.protocol + \"://\" + host + \":\" + Globals.port + \"/wsman\";\r\n\r\n                IWSManSession session = (IWSManSession)wsman.CreateSession(sessionUrl, 0, options);\r\n                if ((user.Length > 0) && (password.Length > 0))\r\n                {\r\n                    options.UserName = user;\r\n                    options.Password = password;\r\n                    session = (IWSManSession)wsman.CreateSession(sessionUrl, wsman.SessionFlagCredUsernamePassword(), options);\r\n                }\r\n\r\n                string resource = \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\";\r\n                string parameters = \"<p:Create_INPUT xmlns:p=\\\"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\\\"><p:CommandLine>\" + cmd + \"</p:CommandLine></p:Create_INPUT>\";\r\n                string response = session.Invoke(\"Create\", resource, parameters);\r\n\r\n                //(Poorly) Parse XML response and print values\r\n                XmlDocument xml = new XmlDocument();\r\n                xml.LoadXml(response);\r\n                Console.WriteLine(\"xsi         : \" + xml.DocumentElement.GetAttribute(\"xmlns:xsi\"));\r\n                Console.WriteLine(\"p           : \" + xml.DocumentElement.GetAttribute(\"xmlns:p\"));\r\n                Console.WriteLine(\"cim         : \" + xml.DocumentElement.GetAttribute(\"xmlns:cim\"));\r\n                Console.WriteLine(\"lang        : \" + xml.DocumentElement.GetAttribute(\"xml:lang\"));\r\n                Console.WriteLine(\"ProcessId   : \" + xml.DocumentElement.ChildNodes[0].InnerText);\r\n                Console.WriteLine(\"ReturnValue : \" + xml.DocumentElement.ChildNodes[1].InnerText);\r\n\r\n                //Cleanup COM Object\r\n                Marshal.ReleaseComObject(session);\r\n                Marshal.ReleaseComObject(options);\r\n            }\r\n            catch (Exception e)\r\n            {\r\n                Console.WriteLine(e.Message.ToString());\r\n            }\r\n        }\r\n    }\r\n}"
  },
  {
    "path": "WSManWinRM.js",
    "content": "/*\r\nWSManWinRM.js\r\n       Purpose: A simple POC for leveraging a WMI class to execute a remote command over the WinRM(WSMan) protocol using the WSMan.Automation COM object (wsmauto.dll)\r\n       Author: @bohops\r\n       License: BSD 3-Clause\r\n\r\n       Usage: cscript.exe WSManWinRM.js [hostname] [command]\r\n       Usage: cscript.exe WSManWinRM.js [hostname] [command] [domain\\user] [password]\r\n\r\n       Example: cscript.exe WSManWinRM.js host.domain.local notepad.exe\r\n       Example: cscript.exe WSManWinRM.js host.domain.local \"cmd /c notepad.exe\" domain\\joe.user P@ssw0rd\r\n\r\n       Link: https://docs.microsoft.com/en-us/windows/win32/winrm/wsman\r\n*/\r\n\r\nvar args = WScript.Arguments;\r\nvar protocol = \"http\";\r\nvar port = \"5985\";\r\n\r\nvar wsman = new ActiveXObject(\"Wsman.Automation\");\r\nvar options = wsman.CreateConnectionOptions();\r\nvar sessionUrl = protocol + \"://\" + args(0) + \":\" + port + \"/wsman\";\r\n\r\nvar session = wsman.CreateSession(sessionUrl, 0, options);\r\nif (args.Count() == 4) \r\n{\r\n    options.UserName = args(2);\r\n    options.Password = args(3);\r\n    session = wsman.CreateSession(sessionUrl, wsman.SessionFlagCredUsernamePassword(), options);\r\n}\r\n\r\nvar resource = \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\";\r\nvar parameters = \"<p:Create_INPUT xmlns:p=\\\"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\\\"><p:CommandLine>\" + args(1) + \"</p:CommandLine></p:Create_INPUT>\";\r\nvar response = session.invoke(\"Create\", resource, parameters);\r\nWScript.Echo(response);"
  },
  {
    "path": "WSManWinRM.ps1",
    "content": "﻿function Invoke-WSManWinRM\r\n{\r\n<#\r\n    .SYNOPSIS\r\n        Purpose: A simple POC for leveraging a WMI class to execute a remote command over the WinRM (WSMan) protocol using the WSMan.Automation COM object (wsmauto.dll)\r\n        Inspiration: Invoke-WSManAction\r\n        Author: @bohops\r\n        License: BSD 3-Clause\r\n    .PARAMETER hostname\r\n        The hostname (or FQDN) of the remote WinRM host. Required.\r\n    .PARAMETER command\r\n        The command to execute remotely. Required.\r\n    .PARAMETER user\r\n        Domain\\Username (credential). Optional.\r\n    .PARAMETER password\r\n        Password (credential). Optional. \r\n    .EXAMPLE\r\n        PS C:\\> Invoke-WSManWinRM -hostname MyServer.domain.local -command calc.exe\r\n        Returns XML Blog with PID if successful\r\n    .EXAMPLE\r\n        PS C:\\> Invoke-WSManWinRM -hostname MyServer.domain.local -command calc.exe -user domain\\joe.user -password P@ssw0rd\r\n        Returns XML Blog with PID if successful\r\n    .LINK\r\n        https://docs.microsoft.com/en-us/windows/win32/winrm/wsman\r\n#>\r\n    Param\r\n    (\r\n         [Parameter(Mandatory=$true, Position=0)]\r\n         [string] $hostname,\r\n         [Parameter(Mandatory=$true, Position=1)]\r\n         [string] $command,\r\n         [Parameter(Mandatory=$false, Position=2)]\r\n         [string] $user,\r\n         [Parameter(Mandatory=$false, Position=3)]\r\n         [string] $password\r\n    )\r\n\r\n    $protocol = \"http\"\r\n    $port = \"5985\"\r\n\r\n    $wsman = new-object -com WSMan.Automation\r\n    $options = $wsman.CreateConnectionOptions()\r\n    $sessionUrl = $protocol + \"://\" + $hostname + \":\" + $port + \"/wsman\"\r\n\r\n    $session = $wsman.CreateSession($sessionUrl, 0, $options)\r\n    if (($user.Length -gt 0) -and ($password.Length -gt 0))\r\n    {\r\n        $options.Username = $user\r\n        $options.Password = $password\r\n        $session = $wsman.CreateSession($sessionUrl, $wsman.SessionFlagCredUsernamePassword(), $options)\r\n    }\r\n\r\n    \r\n    $resource = \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\"\r\n    $parameters = \"<p:Create_INPUT xmlns:p=`\"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process`\"><p:CommandLine>\" + $command + \"</p:CommandLine></p:Create_INPUT>\"\r\n    $response = $session.Invoke(\"Create\", $resource, $parameters)\r\n    write-host $response\r\n}\r\n"
  },
  {
    "path": "WSManWinRM.vbs",
    "content": "'WSManWinRM.vbs\r\n'       Purpose: A simple POC for leveraging a WMI class to execute a remote command over the WinRM(WSMan) protocol using the WSMan.Automation COM object (wsmauto.dll)\r\n'       Inspiration: Invoke-WSManAction (PowerShell)\r\n'       Author: @bohops\r\n'       License: BSD 3-Clause\r\n'\r\n'       Usage: cscript.exe WSManWinRM.vbs [hostname] [command]\r\n'       Usage: cscript.exe WSManWinRM.vbs [hostname] [command] [domain\\user] [password]\r\n'\r\n'       Example: cscript.exe WSManWinRM.vbs host.domain.local notepad.exe\r\n'       Example: cscript.exe WSManWinRM.vbs host.domain.local \"cmd /c notepad.exe\" domain\\joe.user P@ssw0rd\r\n'\r\n'       Link: https://docs.microsoft.com/en-us/windows/win32/winrm/wsman\r\n\r\ndim arg, protocol, port, wsman, session, sessionUrl, resource, options, parameters, response\r\n\r\nset args = wscript.arguments\r\nprotocol = \"http\"\r\nport = \"5985\"\r\n\r\nset wsman = CreateObject(\"Wsman.Automation\")\r\nset options = wsman.CreateConnectionOptions\r\nsessionUrl = protocol + \"://\" + args(0) + \":\" + port + \"/wsman\"\r\n\r\nset session = wsman.CreateSession(sessionUrl, 0, options)\r\nif args.count = 4 then\r\n    options.UserName = args(2)\r\n    options.Password = args(3)\r\n    set session = wsman.CreateSession(sessionUrl, wsman.SessionFlagCredUsernamePassword, options)\r\nend if\r\n\r\n\r\nresource = \"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\"\r\nparameters = \"<p:Create_INPUT xmlns:p=\"\"http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process\"\"><p:CommandLine>\" + args(1) + \"</p:CommandLine></p:Create_INPUT>\"\r\nresponse = session.invoke(\"Create\", resource, parameters)\r\nwscript.echo response"
  }
]