1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-01-08 14:36:22 +01:00
metasploit-payloads/c/meterpreter/source/extensions/python/python_meterpreter_binding.c
OJ c74376fb69
Make enc flags 32 bit, fix extension bindings
This updates the packet header so that the encryption byte flag is now
32 bits. This also updates the powershell and python extensions so that
both of the bindings work correctly as a result of the TLV packet header
changes.
2017-07-03 16:51:57 +10:00

97 lines
3.1 KiB
C
Executable File

/*!
* @file python_meterpreter_binding.c
* @brief Definitions for functions that support meterpreter bindings.
*/
#include "../../common/common.h"
#include "python_main.h"
#include "Python.h"
static PLIST gBoundCommandList = NULL;
static PyObject* gMeterpreterModule = NULL;
static PyMethodDef* gMeterpreterMethods = NULL;
static PLIST gMeterpreterMethodDefs = NULL;
static PyObject* binding_invoke(PyObject* self, PyObject* args)
{
dprintf("[PYTHON] a function was invoked on: %s", self->ob_type->tp_name);
const char* packetBytes = NULL;
BOOL isLocal = FALSE;
Py_ssize_t packetLength = 0;
PyArg_ParseTuple(args, "is#", &isLocal, &packetBytes, &packetLength);
dprintf("[PYTHON] packet %p is %u bytes and is %s", packetBytes, packetLength, isLocal ? "local" : "not local");
Packet packet = { 0 };
packet.header = *(PacketHeader*)packetBytes;
packet.payload = (PUCHAR)(packetBytes + sizeof(PacketHeader));
packet.payloadLength = (ULONG)packetLength - sizeof(PacketHeader);
// If the functionality doesn't require interaction with MSF, then
// make the packet as local so that the packet receives the request
// and so that the packet doesn't get sent to Meterpreter
packet.local = isLocal;
command_handle(gRemote, &packet);
// really not sure how to deal with the non-local responses at this point.
if (packet.partner == NULL)
{
// "None"
return Py_BuildValue("");
}
PyObject* result = PyString_FromStringAndSize(packet.partner->payload, packet.partner->payloadLength);
packet_destroy(packet.partner);
return result;
}
VOID binding_insert_command(const char* commandName)
{
static PyMethodDef def;
dprintf("[PYTHON] inserting command %s", commandName);
def.ml_name = commandName;
def.ml_meth = binding_invoke;
def.ml_flags = METH_VARARGS;
def.ml_doc = NULL;
PyObject* fun = PyCFunction_New(&def, gMeterpreterModule);
PyModule_AddObject(gMeterpreterModule, commandName, fun);
}
VOID binding_startup()
{
if (gBoundCommandList == NULL)
{
gBoundCommandList = list_create();
}
}
VOID binding_add_command(const char* commandName)
{
dprintf("[PYTHON] Adding command %s", (char*)commandName);
// only add non-core commands
if (_strnicmp("core_", commandName, 5) != 0)
{
list_add(gBoundCommandList, (char*)commandName);
binding_insert_command(commandName);
}
}
VOID binding_init()
{
dprintf("[PYTHON] Initialising binding...");
gMeterpreterModule = Py_InitModule("meterpreter_bindings", NULL);
// we have a hard-coded core command binding for all core commands. This allows us to use
// the one function for all base core commands that aren't included as part of the "normal"
// mechanisms for extension loading. Without this, we'd have to manually wire in each of the
// base commands, which doesn't make sense. Instead we can match against core command names
// and funnel through this binding knowing that they'll be there regardless of the wiring.
binding_insert_command("meterpreter_core");
for (PNODE node = gBoundCommandList->start; node != NULL; node = node->next)
{
binding_insert_command((const char*)node->data);
}
}