1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-02-16 00:24:29 +01:00

Handle core commands like they're provided by the pseudo core extension

This commit is contained in:
Spencer McIntyre 2021-01-13 17:58:40 -05:00
parent b03f213d4f
commit ebdcd95615
4 changed files with 83 additions and 79 deletions

View File

@ -104,6 +104,24 @@ Command baseCommands[] =
*/
Command* extensionCommands = NULL;
/*!
* @brief Register dispatch routines provided by the meterpreter core.
*/
Command* register_base_dispatch_routines(void) {
Command* pFirstCommand = NULL;
command_register_all(baseCommands);
pFirstCommand = extensionCommands;
while (pFirstCommand && pFirstCommand->command_id != baseCommands[0].command_id) {
dprintf("[COMMAND LIST] Command: %p command id %u != %u", pFirstCommand, pFirstCommand->command_id, baseCommands[0].command_id);
pFirstCommand = pFirstCommand->next;
}
if (pFirstCommand) {
dprintf("Found first command: %p (id: %u)", pFirstCommand, pFirstCommand->command_id);
}
return pFirstCommand;
}
/*!
* @brief Register a full list of commands with meterpreter.
* @param commands The array of commands that are to be registered for the module/extension.
@ -241,8 +259,7 @@ VOID command_join_threads(VOID)
/*!
* @brief Process a command directly on the current thread.
* @param baseCommand Pointer to the \c Command in the base command list to be executed.
* @param extensionCommand Pointer to the \c Command in the extension command list to be executed.
* @param command Pointer to the \c Command in the extension command list to be executed.
* @param remote Pointer to the \c Remote endpoint for this command.
* @param packet Pointer to the \c Packet containing the command detail.
* @returns Boolean value indicating if the server should continue processing.
@ -254,82 +271,69 @@ VOID command_join_threads(VOID)
* then the result of the \c baseCommand processing is ignored and the result of
* \c extensionCommand is returned instead.
*/
BOOL command_process_inline(Command *baseCommand, Command *extensionCommand, Remote *remote, Packet *packet)
BOOL command_process_inline(Command *command, Remote *remote, Packet *packet)
{
DWORD result;
BOOL serverContinue = TRUE;
Tlv requestIdTlv;
PCHAR requestId;
PacketTlvType packetTlvType;
Command *commands[2] = { baseCommand, extensionCommand };
Command *command = NULL;
DWORD dwIndex;
UINT commandId = 0;
__try
{
do
{
for (dwIndex = 0; dwIndex < 2; ++dwIndex)
commandId = command->command_id;
dprintf("[COMMAND] Executing command %u", commandId);
// Impersonate the thread token if needed (only on Windows)
if (remote->server_token != remote->thread_token)
{
command = commands[dwIndex];
if (command == NULL)
if (!ImpersonateLoggedOnUser(remote->thread_token))
{
continue;
dprintf("[COMMAND] Failed to impersonate thread token (%u) (%u)", commandId, GetLastError());
}
}
commandId = command->command_id;
dprintf("[COMMAND] Executing command %u", commandId);
// Validate the arguments, if requested. Always make sure argument
// lengths are sane.
if (command_validate_arguments(command, packet) != ERROR_SUCCESS)
{
dprintf("[COMMAND] Command arguments failed to validate");
continue;
}
// Impersonate the thread token if needed (only on Windows)
if (remote->server_token != remote->thread_token)
packetTlvType = packet_get_type(packet);
dprintf("[DISPATCH] Packet type for %u is %u", commandId, packetTlvType);
switch (packetTlvType)
{
case PACKET_TLV_TYPE_REQUEST:
case PACKET_TLV_TYPE_PLAIN_REQUEST:
if (command->request.inline_handler) {
dprintf("[DISPATCH] executing inline request handler %u", commandId);
serverContinue = command->request.inline_handler(remote, packet, &result) && serverContinue;
dprintf("[DISPATCH] executed %u, continue %s", commandId, serverContinue ? "yes" : "no");
}
else
{
if (!ImpersonateLoggedOnUser(remote->thread_token))
{
dprintf("[COMMAND] Failed to impersonate thread token (%u) (%u)", commandId, GetLastError());
}
dprintf("[DISPATCH] executing request handler %u", commandId);
result = command->request.handler(remote, packet);
}
// Validate the arguments, if requested. Always make sure argument
// lengths are sane.
if (command_validate_arguments(command, packet) != ERROR_SUCCESS)
break;
case PACKET_TLV_TYPE_RESPONSE:
case PACKET_TLV_TYPE_PLAIN_RESPONSE:
if (command->response.inline_handler)
{
dprintf("[COMMAND] Command arguments failed to validate");
continue;
dprintf("[DISPATCH] executing inline response handler %u", commandId);
serverContinue = command->response.inline_handler(remote, packet, &result) && serverContinue;
}
packetTlvType = packet_get_type(packet);
dprintf("[DISPATCH] Packet type for %u is %u", commandId, packetTlvType);
switch (packetTlvType)
else
{
case PACKET_TLV_TYPE_REQUEST:
case PACKET_TLV_TYPE_PLAIN_REQUEST:
if (command->request.inline_handler) {
dprintf("[DISPATCH] executing inline request handler %u", commandId);
serverContinue = command->request.inline_handler(remote, packet, &result) && serverContinue;
dprintf("[DISPATCH] executed %u, continue %s", commandId, serverContinue ? "yes" : "no");
}
else
{
dprintf("[DISPATCH] executing request handler %u", commandId);
result = command->request.handler(remote, packet);
}
break;
case PACKET_TLV_TYPE_RESPONSE:
case PACKET_TLV_TYPE_PLAIN_RESPONSE:
if (command->response.inline_handler)
{
dprintf("[DISPATCH] executing inline response handler %u", commandId);
serverContinue = command->response.inline_handler(remote, packet, &result) && serverContinue;
}
else
{
dprintf("[DISPATCH] executing response handler %u", commandId);
result = command->response.handler(remote, packet);
}
break;
dprintf("[DISPATCH] executing response handler %u", commandId);
result = command->response.handler(remote, packet);
}
break;
}
dprintf("[COMMAND] Calling completion handlers...");
@ -434,7 +438,6 @@ BOOL command_handle(Remote *remote, Packet *packet)
{
BOOL result = TRUE;
THREAD* cpt = NULL;
Command* baseCommand = NULL;
Command* extensionCommand = NULL;
Command** commands = NULL;
Packet* response = NULL;
@ -450,10 +453,9 @@ BOOL command_handle(Remote *remote, Packet *packet)
break;
}
baseCommand = command_locate_base(commandId);
extensionCommand = command_locate_extension(commandId);
if (baseCommand == NULL && extensionCommand == NULL)
if (extensionCommand == NULL)
{
dprintf("[DISPATCH] Command not found: %u", commandId);
// We have no matching command for this packet, so it won't get handled. We
@ -472,23 +474,18 @@ BOOL command_handle(Remote *remote, Packet *packet)
}
// if either command is registered as inline, run them inline
if ((baseCommand && command_is_inline(baseCommand, packet))
|| (extensionCommand && command_is_inline(extensionCommand, packet))
if ((extensionCommand && command_is_inline(extensionCommand, packet))
|| packet->local)
{
dprintf("[DISPATCH] Executing inline: %u", commandId);
result = command_process_inline(baseCommand, extensionCommand, remote, packet);
result = command_process_inline(extensionCommand, remote, packet);
dprintf("[DISPATCH] Executed inline: result %u (%x)", result, result);
}
else
{
dprintf("[DISPATCH] Executing in thread: %u", commandId);
commands = (Command**)malloc(sizeof(Command*) * 2);
*commands = baseCommand;
*(commands + 1) = extensionCommand;
cpt = thread_create(command_process_thread, remote, packet, commands);
cpt = thread_create(command_process_thread, remote, packet, extensionCommand);
if (cpt)
{
dprintf("[DISPATCH] created command_process_thread 0x%08X, handle=0x%08X", cpt, cpt->handle);
@ -509,7 +506,7 @@ BOOL command_handle(Remote *remote, Packet *packet)
*/
DWORD THREADCALL command_process_thread(THREAD * thread)
{
Command** commands = NULL;
Command* command = NULL;
Remote * remote = NULL;
Packet * packet = NULL;
@ -532,8 +529,8 @@ DWORD THREADCALL command_process_thread(THREAD * thread)
return ERROR_INVALID_DATA;
}
commands = (Command**)thread->parameter3;
if (commands == NULL)
command = (Command*)thread->parameter3;
if (command == NULL)
{
return ERROR_INVALID_DATA;
}
@ -550,19 +547,14 @@ DWORD THREADCALL command_process_thread(THREAD * thread)
list_add(commandThreadList, thread);
// invoke processing inline, passing in both commands
dprintf("[COMMAND] About to execute inline -> Commands: %p Command1: %p Command2: %p", commands, *commands, *(commands + 1));
command_process_inline(*commands, *(commands + 1), remote, packet);
dprintf("[COMMAND] Executed inline -> Commands: %p Command1: %p Command2: %p", commands, *commands, *(commands + 1));
dprintf("[COMMAND] About to execute inline -> Command: %p", command);
command_process_inline(command, remote, packet);
dprintf("[COMMAND] Executed inline -> Command: %p", command);
if (list_remove(commandThreadList, thread))
{
thread_destroy(thread);
}
// free things up now that the command stuff has been finished
dprintf("[COMMAND] Cleaning up commands");
free(commands);
return ERROR_SUCCESS;
}

View File

@ -13,5 +13,6 @@ DWORD command_register(Command *command);
DWORD command_deregister(Command *command);
VOID command_join_threads( VOID );
BOOL command_handle( Remote *remote, Packet *packet );
Command* register_base_dispatch_routines(void);
#endif

View File

@ -94,9 +94,10 @@ BOOL ext_cmd_callback(LPVOID pState, LPVOID pData)
PEXTENSION pExt = (PEXTENSION)pData;
for (command = pExt->start; command != pExt->end; command = command->next)
{
dprintf("[LISTEXTCMD] Processing extension: %p", pExt);
if (pEnum->command_id_start < command->command_id && command->command_id < pEnum->command_id_end)
{
dprintf("[DISPATCH] Adding command ID %u", command->command_id);
dprintf("[LISTEXTCMD] Adding command ID %u", command->command_id);
packet_add_tlv_uint(pEnum->pResponse, TLV_TYPE_UINT, command->command_id);
}
}
@ -153,7 +154,17 @@ VOID register_dispatch_routines()
{
gExtensionList = list_create();
Command* pFirstCommand = register_base_dispatch_routines();
command_register_all(customCommands);
PEXTENSION pExtension = (PEXTENSION)malloc(sizeof(EXTENSION));
if (pExtension) {
memset(pExtension, 0, sizeof(EXTENSION));
pExtension->end = pFirstCommand;
pExtension->start = extensionCommands;
list_push(gExtensionList, pExtension);
dprintf("[EXTENSTION] Registered core pseudo extension %p", pExtension);
}
}
/*

View File

@ -375,7 +375,7 @@ DWORD server_setup(MetsrvConfig* config)
dprintf("[SERVER] Registering dispatch routines...");
register_dispatch_routines();
// this has to be done after dispatch routine are registered
LPBYTE configEnd = load_stageless_extensions(remote, (MetsrvExtension*)((LPBYTE)config->transports + transportSize));