Repository: bohops/WSMan-WinRM Branch: master Commit: 2e3afbf70e2f Files: 7 Total size: 17.9 KB Directory structure: gitextract_68h61zmj/ ├── CppWSManWinRM.cpp ├── LICENSE ├── README.md ├── SharpWSManWinRM.cs ├── WSManWinRM.js ├── WSManWinRM.ps1 └── WSManWinRM.vbs ================================================ FILE CONTENTS ================================================ ================================================ FILE: CppWSManWinRM.cpp ================================================ /* CppWSManWinRM.cpp 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) Author: @bohops License: BSD 3-Clause Usage: CppWSManWinRM.exe [hostname] [command] //Usage: CppWSManWinRM.exe [hostname] [command] [domain\user] [password] <-- Does not work...yet Example: CppWSManWinRM.exe host.domain.local notepad.exe //Example: CppWSManWinRM.exe host.domain.local "cmd /c notepad.exe" domain\joe.user P@ssw0rd <-- Does not work...yet Link: http://forums.codeguru.com/showthread.php?499875-WSManAutomation-lib-is-missing (Primary Code Source -> credit: ssoma from CodeGuru forums) Link: https://docs.microsoft.com/en-us/windows/win32/winrm/wsman */ #include #include #include #include "wsmandisp_i.c" #include using namespace std; int ExecRemoteCmd(string host, string cmd, string user, string passwd); int main(int argc, char** argv) { if (argc == 3) //Args: 2 (+ 1) int res = ExecRemoteCmd(argv[1], argv[2], "", ""); else if (argc == 5) //Args: 4 (+1) cout << ":-|"; //int res = ExecRemoteCmd(argv[1], argv[2], argv[3], argv[4]); <--- not implemented....yet else { cout << "Usage: CppWSManWinRM.exe [hostname] [command]" << endl; cout << "Example: CppWSManWinRM.exe host.domain.local \"cmd /c notepad.exe\"" << endl; //cout << " -or-" << endl; //cout << "Usage: CppWSManWinRM.exe [hostname] [command] [domain\\user] [password]" << endl; //cout << "Example: CppWSManWinRM.exe host.domain.local \"cmd /c notepad.exe\" domain\\joe.user P@ssw0rd" << endl; } } int ExecRemoteCmd(string host, string cmd, string user, string passwd) { _bstr_t protocol = "http"; _bstr_t port = "5985"; _bstr_t hostname = (_bstr_t)host.c_str(); _bstr_t command = (_bstr_t)cmd.c_str(); //_bstr_t username = (_bstr_t)user.c_str(); //_bstr_t password = (_bstr_t)passwd.c_str(); HRESULT hres = NULL; HRESULT hr = S_OK; IDispatch* pSvc = NULL; IDispatch* pOptions = NULL; IWSManSession* pSvc1 = NULL; // Initialize COM hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl; return 1; // Program has failed. } //Instatliate WSMAN COM Object IWSMan* pLoc = NULL; hres = CoCreateInstance(CLSID_WSMan, 0, CLSCTX_INPROC_SERVER, IID_IWSMan, (LPVOID*)&pLoc); if (FAILED(hres)) { cout << "Failed to create IWSMan object." << " Err code = 0x" << hex << hres << endl; CoUninitialize(); return 1; // Program has failed. } //Create Remote Session cout << "[*] Creating session with the remote system..." << endl; pSvc = reinterpret_cast(pSvc1); long f = 0; // This needs to be fixed for supplied credentials. Pull requests welcome... //if ("creds") //{ // //HRESULT SessionFlagUseNoAuthentication(f); // HRESULT SessionFlagCredUsernamePassword(f); // IWSManConnectionOptions* options = NULL; // options->put_UserName(bstr_t("corp\\corpmin")); // options->put_Password(bstr_t("CorpM@ster")); // pOptions = reinterpret_cast(options); // hres = pLoc->CreateConnectionOptions(&pOptions); // hres = pLoc->CreateSession(_bstr_t("http://corp-dc:5985/wsman"), f, pOptions, &pSvc); //} //else //{ // hres = pLoc->CreateSession(_bstr_t("http://corp-dc:5985/wsman"), 0, NULL, &pSvc); //} hres = pLoc->CreateSession(protocol + _bstr_t("://") + hostname + _bstr_t(":") + port + _bstr_t("/wsman"), 0, NULL, &pSvc); if (FAILED(hres)) { cout << "Could not connect. Error code = 0x" << hex << hres << endl; pLoc->Release(); CoUninitialize(); return 1; // Program has failed. } //Invoke Command cout << "[*] Connected to the remote WinRM system" << endl; pSvc1 = reinterpret_cast(pSvc); _variant_t resource = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process"; _bstr_t parameters = "" + command + ""; wchar_t* response = new wchar_t(1000); hres = pSvc1->Invoke(_bstr_t("Create"), resource, parameters, 0, &response); //Print Response cout << "[*] Result Code: " << response; //Cleanup pSvc->Release(); pSvc1->Release(); pOptions->Release(); pLoc->Release(); CoUninitialize(); return 0; } ================================================ FILE: LICENSE ================================================ BSD 3-Clause License Copyright (c) 2020, bohops All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================ # WSMan-WinRM A collection of proof-of-concept source code and scripts for executing remote commands over WinRM using the WSMan.Automation COM object. ## Background For 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/) ## Notes - SharpWSManWinRM.cs and CppWsManWinRM.cpp compile in Visual Studio 2019. Refer to the code comments for required imports/references/etc. - All examples leverage the WMI Win32_Process class and WMI Create method for invocation. ## Usage ### SharpWSManWinRM.cs ``` Usage: SharpWSManWinRM.exe Usage: SharpWSManWinRM.exe Example: SharpWSManWinRM.exe host.domain.local notepad.exe Example: SharpWSManWinRM.exe host.domain.local "cmd /c notepad.exe" domain\joe.user P@ssw0rd ``` ### WSManWinRM.ps1 ``` Usage: Invoke-WSManWinRM -hostname -command Usage: Invoke-WSManWinRM -hostname -command -user -password Example: import-module .\WSManWinRM.ps1 Invoke-WSManWinRM -hostname MyServer.domain.local -command calc.exe Example: import-module .\WSManWinRM.ps1 Invoke-WSManWinRM -hostname MyServer.domain.local -command calc.exe -user domain\joe.user -password P@ssw0rd ``` ### WSManWinRM.vbs ``` Usage: cscript.exe SharpWSManWinRM.vbs Usage: cscript.exe SharpWSManWinRM.vbs Example: cscript.exe SharpWSManWinRM.vbs host.domain.local notepad.exe Example: cscript.exe SharpWSManWinRM.vbs host.domain.local "cmd /c notepad.exe" domain\joe.user P@ssw0rd ``` ### WSManWinRM.js ``` Usage: cscript.exe SharpWSManWinRM.js Usage: cscript.exe SharpWSManWinRM.js Example: cscript.exe SharpWSManWinRM.js host.domain.local notepad.exe Example: cscript.exe SharpWSManWinRM.js host.domain.local "cmd /c notepad.exe" domain\joe.user P@ssw0rd ``` ### CppWSManWinRM.cpp ``` Usage: CppWSManWinRM.exe Example: CppWSManWinRM.exe host.domain.local notepad.exe Note: Username/password option does not work yet ``` ## Ethics WSMan-WinRM is designed to help security professionals perform ethical and legal security assessments and penetration tests. Do not use for nefarious purposes. ================================================ FILE: SharpWSManWinRM.cs ================================================ /* SharpWSManWinRM.cs 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) Author: @bohops License: BSD 3-Clause Usage: SharpWSManWinRM.exe [hostname] [command] Usage: SharpWSManWinRM.exe [hostname] [command] [domain\user] [password] Example: SharpWSManWinRM.exe host.domain.local notepad.exe Example: SharpWSManWinRM.exe host.domain.local "cmd /c notepad.exe" domain\joe.user P@ssw0rd Link: https://docs.microsoft.com/en-us/windows/win32/winrm/wsman */ using System; using System.Runtime.InteropServices; using System.Xml; using WSManAutomation; //Add Reference -> windows\system32\wsmauto.dll (or COM: Microsoft WSMan Automation V 1.0 Library) namespace SharpWinRM { //Globals vars to store protocol/port info for now before testing out TLS/SSL public class Globals { public const string protocol = "http"; public const string port = "5985"; } class Program { static void Main(string[] args) { if (args.Length == 2) ExecRemoteCmd(args[0], args[1], "", ""); else if (args.Length == 4) ExecRemoteCmd(args[0], args[1], args[2], args[3]); else { Console.WriteLine("Usage: SharpWSManWinRM.exe [hostname] [command]\n" + "Example: SharpWSManWinRM.exe host.domain.local \"cmd /c notepad.exe\""); Console.WriteLine("\n -or-\n"); Console.WriteLine("Usage: SharpWSManWinRM.exe [hostname] [command] [domain\\user] [password]\n" + "Example: SharpWSManWinRM.exe host.domain.local \"cmd /c notepad.exe\" domain\\joe.user P@ssw0rd"); } } static void ExecRemoteCmd(string host, string cmd, string user, string password) { try { //Setup session & execute remote command IWSManEx wsman = new WSMan(); IWSManConnectionOptions options = (IWSManConnectionOptions)wsman.CreateConnectionOptions(); string sessionUrl = Globals.protocol + "://" + host + ":" + Globals.port + "/wsman"; IWSManSession session = (IWSManSession)wsman.CreateSession(sessionUrl, 0, options); if ((user.Length > 0) && (password.Length > 0)) { options.UserName = user; options.Password = password; session = (IWSManSession)wsman.CreateSession(sessionUrl, wsman.SessionFlagCredUsernamePassword(), options); } string resource = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process"; string parameters = "" + cmd + ""; string response = session.Invoke("Create", resource, parameters); //(Poorly) Parse XML response and print values XmlDocument xml = new XmlDocument(); xml.LoadXml(response); Console.WriteLine("xsi : " + xml.DocumentElement.GetAttribute("xmlns:xsi")); Console.WriteLine("p : " + xml.DocumentElement.GetAttribute("xmlns:p")); Console.WriteLine("cim : " + xml.DocumentElement.GetAttribute("xmlns:cim")); Console.WriteLine("lang : " + xml.DocumentElement.GetAttribute("xml:lang")); Console.WriteLine("ProcessId : " + xml.DocumentElement.ChildNodes[0].InnerText); Console.WriteLine("ReturnValue : " + xml.DocumentElement.ChildNodes[1].InnerText); //Cleanup COM Object Marshal.ReleaseComObject(session); Marshal.ReleaseComObject(options); } catch (Exception e) { Console.WriteLine(e.Message.ToString()); } } } } ================================================ FILE: WSManWinRM.js ================================================ /* WSManWinRM.js 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) Author: @bohops License: BSD 3-Clause Usage: cscript.exe WSManWinRM.js [hostname] [command] Usage: cscript.exe WSManWinRM.js [hostname] [command] [domain\user] [password] Example: cscript.exe WSManWinRM.js host.domain.local notepad.exe Example: cscript.exe WSManWinRM.js host.domain.local "cmd /c notepad.exe" domain\joe.user P@ssw0rd Link: https://docs.microsoft.com/en-us/windows/win32/winrm/wsman */ var args = WScript.Arguments; var protocol = "http"; var port = "5985"; var wsman = new ActiveXObject("Wsman.Automation"); var options = wsman.CreateConnectionOptions(); var sessionUrl = protocol + "://" + args(0) + ":" + port + "/wsman"; var session = wsman.CreateSession(sessionUrl, 0, options); if (args.Count() == 4) { options.UserName = args(2); options.Password = args(3); session = wsman.CreateSession(sessionUrl, wsman.SessionFlagCredUsernamePassword(), options); } var resource = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process"; var parameters = "" + args(1) + ""; var response = session.invoke("Create", resource, parameters); WScript.Echo(response); ================================================ FILE: WSManWinRM.ps1 ================================================ function Invoke-WSManWinRM { <# .SYNOPSIS 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) Inspiration: Invoke-WSManAction Author: @bohops License: BSD 3-Clause .PARAMETER hostname The hostname (or FQDN) of the remote WinRM host. Required. .PARAMETER command The command to execute remotely. Required. .PARAMETER user Domain\Username (credential). Optional. .PARAMETER password Password (credential). Optional. .EXAMPLE PS C:\> Invoke-WSManWinRM -hostname MyServer.domain.local -command calc.exe Returns XML Blog with PID if successful .EXAMPLE PS C:\> Invoke-WSManWinRM -hostname MyServer.domain.local -command calc.exe -user domain\joe.user -password P@ssw0rd Returns XML Blog with PID if successful .LINK https://docs.microsoft.com/en-us/windows/win32/winrm/wsman #> Param ( [Parameter(Mandatory=$true, Position=0)] [string] $hostname, [Parameter(Mandatory=$true, Position=1)] [string] $command, [Parameter(Mandatory=$false, Position=2)] [string] $user, [Parameter(Mandatory=$false, Position=3)] [string] $password ) $protocol = "http" $port = "5985" $wsman = new-object -com WSMan.Automation $options = $wsman.CreateConnectionOptions() $sessionUrl = $protocol + "://" + $hostname + ":" + $port + "/wsman" $session = $wsman.CreateSession($sessionUrl, 0, $options) if (($user.Length -gt 0) -and ($password.Length -gt 0)) { $options.Username = $user $options.Password = $password $session = $wsman.CreateSession($sessionUrl, $wsman.SessionFlagCredUsernamePassword(), $options) } $resource = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process" $parameters = "" + $command + "" $response = $session.Invoke("Create", $resource, $parameters) write-host $response } ================================================ FILE: WSManWinRM.vbs ================================================ 'WSManWinRM.vbs ' 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) ' Inspiration: Invoke-WSManAction (PowerShell) ' Author: @bohops ' License: BSD 3-Clause ' ' Usage: cscript.exe WSManWinRM.vbs [hostname] [command] ' Usage: cscript.exe WSManWinRM.vbs [hostname] [command] [domain\user] [password] ' ' Example: cscript.exe WSManWinRM.vbs host.domain.local notepad.exe ' Example: cscript.exe WSManWinRM.vbs host.domain.local "cmd /c notepad.exe" domain\joe.user P@ssw0rd ' ' Link: https://docs.microsoft.com/en-us/windows/win32/winrm/wsman dim arg, protocol, port, wsman, session, sessionUrl, resource, options, parameters, response set args = wscript.arguments protocol = "http" port = "5985" set wsman = CreateObject("Wsman.Automation") set options = wsman.CreateConnectionOptions sessionUrl = protocol + "://" + args(0) + ":" + port + "/wsman" set session = wsman.CreateSession(sessionUrl, 0, options) if args.count = 4 then options.UserName = args(2) options.Password = args(3) set session = wsman.CreateSession(sessionUrl, wsman.SessionFlagCredUsernamePassword, options) end if resource = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process" parameters = "" + args(1) + "" response = session.invoke("Create", resource, parameters) wscript.echo response