From 175d6d93f1db190e1bbf43b1bb7dc37da027b241 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 10 Nov 2015 15:43:59 +1000 Subject: [PATCH 1/3] First pass of stageless initialisation script --- c/meterpreter/source/common/config.h | 4 ++++ .../source/extensions/python/python_main.c | 12 ++++++++++ c/meterpreter/source/server/metsrv.h | 2 ++ c/meterpreter/source/server/remote_dispatch.h | 3 ++- .../source/server/server_setup_win.c | 20 +++++++++++++--- .../source/server/win/remote_dispatch.c | 23 +++++++++++++++++-- 6 files changed, 58 insertions(+), 6 deletions(-) mode change 100644 => 100755 c/meterpreter/source/common/config.h mode change 100644 => 100755 c/meterpreter/source/server/remote_dispatch.h diff --git a/c/meterpreter/source/common/config.h b/c/meterpreter/source/common/config.h old mode 100644 new mode 100755 index fddc05fb..2b5277d0 --- a/c/meterpreter/source/common/config.h +++ b/c/meterpreter/source/common/config.h @@ -69,6 +69,10 @@ typedef struct _MetsrvConfig MetsrvSession session; MetsrvTransportCommon transports[1]; ///! Placeholder for 0 or more transports // Extensions will appear after this + // After extensions, we get a list of extension initialisers + // \x00 + // \x00 + // \x00 } MetsrvConfig; #endif diff --git a/c/meterpreter/source/extensions/python/python_main.c b/c/meterpreter/source/extensions/python/python_main.c index 47c4d645..ccb5e0d4 100755 --- a/c/meterpreter/source/extensions/python/python_main.c +++ b/c/meterpreter/source/extensions/python/python_main.c @@ -110,3 +110,15 @@ DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize) strncpy_s(buffer, bufferSize, "python", bufferSize - 1); return ERROR_SUCCESS; } + +/*! + * @brief Do a stageless initialisation of the extension. + * @param buffer Pointer to the buffer that contains the init data. + * @param bufferSize Size of the \c buffer parameter. + * @return Indication of success or failure. + */ +DWORD __declspec(dllexport) StagelessInit(const LPBYTE buffer, DWORD bufferSize) +{ + PyRun_SimpleString((LPCSTR)buffer); + return ERROR_SUCCESS; +} \ No newline at end of file diff --git a/c/meterpreter/source/server/metsrv.h b/c/meterpreter/source/server/metsrv.h index b3e3766d..15b7e85b 100755 --- a/c/meterpreter/source/server/metsrv.h +++ b/c/meterpreter/source/server/metsrv.h @@ -35,6 +35,7 @@ typedef DWORD (*PSRVINIT)(Remote *remote); typedef DWORD (*PSRVDEINIT)(Remote *remote); typedef DWORD (*PSRVGETNAME)(char* buffer, int bufferSize); typedef VOID (*PCMDADDED)(const char* commandName); +typedef DWORD (*PSTAGELESSINIT)(LPBYTE data, DWORD dataSize); typedef struct _EXTENSION { @@ -43,6 +44,7 @@ typedef struct _EXTENSION PSRVDEINIT deinit; PSRVGETNAME getname; PCMDADDED commandAdded; + PSTAGELESSINIT stagelessInit; Command* start; Command* end; char name[16]; diff --git a/c/meterpreter/source/server/remote_dispatch.h b/c/meterpreter/source/server/remote_dispatch.h old mode 100644 new mode 100755 index 8b5a2685..df5858c0 --- a/c/meterpreter/source/server/remote_dispatch.h +++ b/c/meterpreter/source/server/remote_dispatch.h @@ -4,7 +4,8 @@ DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket); DWORD request_core_loadlib(Remote *pRemote, Packet *pPacket); -DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemote, Packet* pResponse, Command* pFirstCommand); +DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemote, Packet* pResponse, Command* pFirstCommand); +DWORD stagelessinit_extension(const char* extensionName, LPBYTE data, DWORD dataSize); VOID register_dispatch_routines(); VOID deregister_dispatch_routines(Remote * remote); diff --git a/c/meterpreter/source/server/server_setup_win.c b/c/meterpreter/source/server/server_setup_win.c index 2de2c830..25ee0589 100755 --- a/c/meterpreter/source/server/server_setup_win.c +++ b/c/meterpreter/source/server/server_setup_win.c @@ -77,10 +77,23 @@ VOID load_stageless_extensions(Remote* remote, MetsrvExtension* stagelessExtensi { dprintf("[SERVER] Extension located at 0x%p: %u bytes", stagelessExtensions->dll, stagelessExtensions->size); HMODULE hLibrary = LoadLibraryR(stagelessExtensions->dll, stagelessExtensions->size); - initialise_extension(hLibrary, TRUE, remote, NULL, extensionCommands); + load_extension(hLibrary, TRUE, remote, NULL, extensionCommands); stagelessExtensions = (MetsrvExtension*)((LPBYTE)stagelessExtensions->dll + stagelessExtensions->size); } + // once we have reached the end, we may have extension initializers + LPBYTE initData = (LPBYTE)(&stagelessExtensions->size) + sizeof(stagelessExtensions->size); + + while (initData != NULL && *initData != '\0') + { + const char* extensionName = (const char*)initData; + LPBYTE data = initData + strlen(extensionName) + 1 + sizeof(DWORD); + DWORD dataSize = *(DWORD*)(data - sizeof(DWORD)); + dprintf("[STAGELESS] init data at %p, name %s, size is %d", extensionName, extensionName, dataSize); + stagelessinit_extension(extensionName, data, dataSize); + initData = data + dataSize; + } + dprintf("[SERVER] All stageless extensions loaded"); } @@ -346,8 +359,6 @@ DWORD server_setup(MetsrvConfig* config) ((TcpTransportContext*)remote->transport->ctx)->fd = (SOCKET)config->session.comms_fd; } - load_stageless_extensions(remote, (MetsrvExtension*)((LPBYTE)config->transports + transportSize)); - // Set up the transport creation function pointer remote->trans_create = create_transport; // Set up the transport removal function pointer @@ -386,6 +397,9 @@ DWORD server_setup(MetsrvConfig* config) dprintf("[SERVER] Registering dispatch routines..."); register_dispatch_routines(); + // this has to be done after dispatch routine are registered + load_stageless_extensions(remote, (MetsrvExtension*)((LPBYTE)config->transports + transportSize)); + remote->sess_start_time = current_unix_timestamp(); // loop through the transports, reconnecting each time. diff --git a/c/meterpreter/source/server/win/remote_dispatch.c b/c/meterpreter/source/server/win/remote_dispatch.c index 2bbd6468..a02b3567 100755 --- a/c/meterpreter/source/server/win/remote_dispatch.c +++ b/c/meterpreter/source/server/win/remote_dispatch.c @@ -8,7 +8,24 @@ extern PLIST gExtensionList; // see common/base.c extern Command *extensionCommands; -DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemote, Packet* pResponse, Command* pFirstCommand) +DWORD stagelessinit_extension(const char* extensionName, LPBYTE data, DWORD dataSize) +{ + dprintf("[STAGELESSINIT] searching for extension init for %s in %p", extensionName, gExtensionList); + dprintf("[STAGELESSINIT] extension list start is %p", gExtensionList->start); + for (PNODE node = gExtensionList->start; node != NULL; node = node->next) + { + PEXTENSION ext = (PEXTENSION)node->data; + dprintf("[STAGELESSINIT] comparing to %s (init is %p)", ext->name, ext->stagelessInit); + if (strcmp(ext->name, extensionName) == 0 && ext->stagelessInit != NULL) + { + dprintf("[STAGELESSINIT] found for %s", extensionName); + return ext->stagelessInit(data, dataSize); + } + } + return ERROR_NOT_FOUND; +} + +DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemote, Packet* pResponse, Command* pFirstCommand) { DWORD dwResult = ERROR_OUTOFMEMORY; PEXTENSION pExtension = (PEXTENSION)malloc(sizeof(EXTENSION)); @@ -27,6 +44,7 @@ DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pExtension->deinit = (PSRVDEINIT)GetProcAddressR(pExtension->library, "DeinitServerExtension"); pExtension->getname = (PSRVGETNAME)GetProcAddressR(pExtension->library, "GetExtensionName"); pExtension->commandAdded = (PCMDADDED)GetProcAddressR(pExtension->library, "CommandAdded"); + pExtension->stagelessInit = (PSTAGELESSINIT)GetProcAddressR(pExtension->library, "StagelessInit"); } else { @@ -34,6 +52,7 @@ DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pExtension->deinit = (PSRVDEINIT)GetProcAddress(pExtension->library, "DeinitServerExtension"); pExtension->getname = (PSRVGETNAME)GetProcAddress(pExtension->library, "GetExtensionName"); pExtension->commandAdded = (PCMDADDED)GetProcAddress(pExtension->library, "CommandAdded"); + pExtension->stagelessInit = (PSTAGELESSINIT)GetProcAddress(pExtension->library, "StagelessInit"); } // patch in the metsrv.dll's HMODULE handle, used by the server extensions for delay loading @@ -207,7 +226,7 @@ DWORD request_core_loadlib(Remote *pRemote, Packet *pPacket) // call its Init routine if ((flags & LOAD_LIBRARY_FLAG_EXTENSION) && library) { - res = initialise_extension(library, bLibLoadedReflectivly, pRemote, response, first); + res = load_extension(library, bLibLoadedReflectivly, pRemote, response, first); } } while (0); From c692e76332ce4f92769a8e3588bf481c1591c6d0 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 10 Nov 2015 20:00:34 +1000 Subject: [PATCH 2/3] Finalise stageless initialisation scripts --- c/meterpreter/source/server/metsrv.c | 5 +++-- c/meterpreter/source/server/server_setup_win.c | 16 +++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) mode change 100644 => 100755 c/meterpreter/source/server/metsrv.c diff --git a/c/meterpreter/source/server/metsrv.c b/c/meterpreter/source/server/metsrv.c old mode 100644 new mode 100755 index e7276bcf..ddfaf155 --- a/c/meterpreter/source/server/metsrv.c +++ b/c/meterpreter/source/server/metsrv.c @@ -14,8 +14,9 @@ DWORD __declspec(dllexport) Init(SOCKET fd) { // In the case of metsrv payloads, the parameter passed to init is NOT a socket, it's actually - // a pointer to the metserv configuration, so do a nasty cast and move on. - MetsrvConfig* metConfig = (MetsrvConfig*)fd; + // a pointer to the metserv configuration, so do a nasty cast and move on. + MetsrvConfig* metConfig = (MetsrvConfig*)fd; + dprintf("[METSRV] Getting ready to init with config %p", metConfig); DWORD result = server_setup(metConfig); dprintf("[METSRV] Exiting with %08x", metConfig->session.exit_func); diff --git a/c/meterpreter/source/server/server_setup_win.c b/c/meterpreter/source/server/server_setup_win.c index 25ee0589..fe59f21c 100755 --- a/c/meterpreter/source/server/server_setup_win.c +++ b/c/meterpreter/source/server/server_setup_win.c @@ -81,6 +81,8 @@ VOID load_stageless_extensions(Remote* remote, MetsrvExtension* stagelessExtensi stagelessExtensions = (MetsrvExtension*)((LPBYTE)stagelessExtensions->dll + stagelessExtensions->size); } + dprintf("[SERVER] All stageless extensions loaded"); + // once we have reached the end, we may have extension initializers LPBYTE initData = (LPBYTE)(&stagelessExtensions->size) + sizeof(stagelessExtensions->size); @@ -94,7 +96,7 @@ VOID load_stageless_extensions(Remote* remote, MetsrvExtension* stagelessExtensi initData = data + dataSize; } - dprintf("[SERVER] All stageless extensions loaded"); + dprintf("[SERVER] All stageless extensions initialised"); } static Transport* create_transport(Remote* remote, MetsrvTransportCommon* transportCommon, LPDWORD size) @@ -369,6 +371,12 @@ DWORD server_setup(MetsrvConfig* config) // Store our thread handle remote->server_thread = serverThread->handle; + dprintf("[SERVER] Registering dispatch routines..."); + register_dispatch_routines(); + + // this has to be done after dispatch routine are registered + load_stageless_extensions(remote, (MetsrvExtension*)((LPBYTE)config->transports + transportSize)); + // Store our process token if (!OpenThreadToken(remote->server_thread, TOKEN_ALL_ACCESS, TRUE, &remote->server_token)) { @@ -394,12 +402,6 @@ DWORD server_setup(MetsrvConfig* config) remote->orig_desktop_name = _strdup(desktopName); remote->curr_desktop_name = _strdup(desktopName); - dprintf("[SERVER] Registering dispatch routines..."); - register_dispatch_routines(); - - // this has to be done after dispatch routine are registered - load_stageless_extensions(remote, (MetsrvExtension*)((LPBYTE)config->transports + transportSize)); - remote->sess_start_time = current_unix_timestamp(); // loop through the transports, reconnecting each time. From 29c86390257651fa517378c41c5a44003a9d49ad Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 20 Nov 2015 12:49:36 +1000 Subject: [PATCH 3/3] Updated init script method --- .../extensions/python/python_commands.c | 131 +++++++++--------- .../extensions/python/python_commands.h | 6 + .../source/extensions/python/python_main.c | 3 +- 3 files changed, 76 insertions(+), 64 deletions(-) mode change 100644 => 100755 c/meterpreter/source/extensions/python/python_commands.c mode change 100644 => 100755 c/meterpreter/source/extensions/python/python_commands.h mode change 100644 => 100755 c/meterpreter/source/extensions/python/python_main.c diff --git a/c/meterpreter/source/extensions/python/python_commands.c b/c/meterpreter/source/extensions/python/python_commands.c old mode 100644 new mode 100755 index 3af53395..2bf1361f --- a/c/meterpreter/source/extensions/python/python_commands.c +++ b/c/meterpreter/source/extensions/python/python_commands.c @@ -9,11 +9,6 @@ #include "python_meterpreter_binding.h" #include "Resource Files/python_core.rh" -///! @brief List of valid python code types for loading -#define PY_CODE_TYPE_STRING 0 -#define PY_CODE_TYPE_PY 1 -#define PY_CODE_TYPE_PYC 2 - ///! @brief Struct that contains pointer to init function and name. typedef struct _InitFunc { @@ -413,6 +408,69 @@ DWORD request_python_reset(Remote* remote, Packet* packet) return ERROR_SUCCESS; } +VOID python_execute(CHAR* modName, LPBYTE pythonCode, DWORD codeLength, UINT codeType, CHAR* resultVar, Packet* responsePacket) +{ + PyObject* mainModule = PyImport_AddModule("__main__"); + PyObject* mainDict = PyModule_GetDict(mainModule); + + if (pythonCode != NULL) + { + if (codeType == PY_CODE_TYPE_STRING) + { + dprintf("[PYTHON] attempting to run string: %s", pythonCode); + + PyRun_SimpleString(pythonCode); + } + else + { + dprintf("[PYTHON] module name: %s", modName); + if (modName) + { + PyObject* pyModName = PyString_FromString(modName); + PyModule_AddObject(mainModule, "met_mod_name", pyModName); + } + + if (codeType == PY_CODE_TYPE_PY) + { + dprintf("[PYTHON] importing .py file"); + + PyObject* pyModBody = PyString_FromString(pythonCode); + PyModule_AddObject(mainModule, "met_mod_body", pyModBody); + } + else + { + dprintf("[PYTHON] importing .pyc file"); + // must be a pyc file + PyObject* pyModBody = PyString_FromStringAndSize(pythonCode, codeLength); + dprintf("[PYTHON] myModBody %p: %s", pyModBody, pyModBody->ob_type->tp_name); + PyModule_AddObject(mainModule, "met_mod_body", pyModBody); + } + + dprintf("[PYTHON] executing import, GO GO GO !"); + PyRun_SimpleString("met_import_code()"); + } + + if (resultVar && responsePacket) + { + PyObject* result = PyDict_GetItemString(mainDict, resultVar); + if (result != NULL) + { + if (PyString_Check(result)) + { + // result is already a string + packet_add_tlv_string(responsePacket, TLV_TYPE_EXTENSION_PYTHON_RESULT, PyString_AsString(result)); + } + else + { + PyObject* resultStr = PyObject_Str(result); + packet_add_tlv_string(responsePacket, TLV_TYPE_EXTENSION_PYTHON_RESULT, PyString_AsString(resultStr)); + Py_DECREF(resultStr); + } + } + } + } +} + /*! * @brief Execute a block of python given in a string and return the result/output. * @param remote Pointer to the \c Remote making the request. @@ -430,65 +488,12 @@ DWORD request_python_execute(Remote* remote, Packet* packet) if (pythonCode != NULL) { - UINT codeType = packet_get_tlv_value_uint(packet, TLV_TYPE_EXTENSION_PYTHON_CODE_TYPE); + UINT codeType = packet_get_tlv_value_uint(packet, TLV_TYPE_EXTENSION_PYTHON_CODE_TYPE); + CHAR* modName = packet_get_tlv_value_string(packet, TLV_TYPE_EXTENSION_PYTHON_NAME); + UINT pythonCodeLength = packet_get_tlv_value_uint(packet, TLV_TYPE_EXTENSION_PYTHON_CODE_LEN); + CHAR* resultVar = packet_get_tlv_value_string(packet, TLV_TYPE_EXTENSION_PYTHON_RESULT_VAR); + python_execute(modName, pythonCode, pythonCodeLength, codeType, resultVar, response); - if (codeType == PY_CODE_TYPE_STRING) - { - dprintf("[PYTHON] attempting to run string: %s", pythonCode); - - PyRun_SimpleString(pythonCode); - } - else - { - CHAR* modName = packet_get_tlv_value_string(packet, TLV_TYPE_EXTENSION_PYTHON_NAME); - dprintf("[PYTHON] module name: %s", modName); - if (modName) - { - PyObject* pyModName = PyString_FromString(modName); - PyModule_AddObject(mainModule, "met_mod_name", pyModName); - } - - if (codeType == PY_CODE_TYPE_PY) - { - dprintf("[PYTHON] importing .py file"); - - PyObject* pyModBody = PyString_FromString(pythonCode); - PyModule_AddObject(mainModule, "met_mod_body", pyModBody); - } - else - { - dprintf("[PYTHON] importing .pyc file"); - // must be a pyc file - UINT pythonCodeLength = packet_get_tlv_value_uint(packet, TLV_TYPE_EXTENSION_PYTHON_CODE_LEN); - PyObject* pyModBody = PyString_FromStringAndSize(pythonCode, pythonCodeLength); - dprintf("[PYTHON] myModBody %p: %s", pyModBody, pyModBody->ob_type->tp_name); - PyModule_AddObject(mainModule, "met_mod_body", pyModBody); - } - - dprintf("[PYTHON] executing import, GO GO GO !"); - PyRun_SimpleString("met_import_code()"); - } - - CHAR* resultVar = packet_get_tlv_value_string(packet, TLV_TYPE_EXTENSION_PYTHON_RESULT_VAR); - if (resultVar) - { - PyObject* result = PyDict_GetItemString(mainDict, resultVar); - if (result != NULL) - { - if (PyString_Check(result)) - { - // result is already a string - packet_add_tlv_string(response, TLV_TYPE_EXTENSION_PYTHON_RESULT, PyString_AsString(result)); - } - else - { - PyObject* resultStr = PyObject_Str(result); - packet_add_tlv_string(response, TLV_TYPE_EXTENSION_PYTHON_RESULT, PyString_AsString(resultStr)); - Py_DECREF(resultStr); - } - } - } - dump_to_packet(stderrBuffer, response, TLV_TYPE_EXTENSION_PYTHON_STDERR); clear_std_handler(stderrBuffer); dump_to_packet(stdoutBuffer, response, TLV_TYPE_EXTENSION_PYTHON_STDOUT); diff --git a/c/meterpreter/source/extensions/python/python_commands.h b/c/meterpreter/source/extensions/python/python_commands.h old mode 100644 new mode 100755 index f7a7921c..863a66d7 --- a/c/meterpreter/source/extensions/python/python_commands.h +++ b/c/meterpreter/source/extensions/python/python_commands.h @@ -6,9 +6,15 @@ #define _METERPRETER_SOURCE_EXTENSION_PYTHON_PYTHON_COMMANDS #include "../../common/common.h" + +///! @brief List of valid python code types for loading +#define PY_CODE_TYPE_STRING 0 +#define PY_CODE_TYPE_PY 1 +#define PY_CODE_TYPE_PYC 2 VOID python_prepare_session(); VOID python_destroy_session(); +VOID python_execute(CHAR* modName, LPBYTE pythonCode, DWORD codeLength, UINT codeType, CHAR* resultVar, Packet* responsePacket); DWORD request_python_reset(Remote* remote, Packet* packet); DWORD request_python_execute(Remote* remote, Packet* packet); diff --git a/c/meterpreter/source/extensions/python/python_main.c b/c/meterpreter/source/extensions/python/python_main.c old mode 100644 new mode 100755 index ccb5e0d4..9b946ffc --- a/c/meterpreter/source/extensions/python/python_main.c +++ b/c/meterpreter/source/extensions/python/python_main.c @@ -119,6 +119,7 @@ DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize) */ DWORD __declspec(dllexport) StagelessInit(const LPBYTE buffer, DWORD bufferSize) { - PyRun_SimpleString((LPCSTR)buffer); + dprintf("[PYTHON] Executing stagless script:\n%s", (LPCSTR)buffer); + python_execute(NULL, (LPSTR)buffer, bufferSize, PY_CODE_TYPE_PY, NULL, NULL); return ERROR_SUCCESS; } \ No newline at end of file