mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-03-30 22:19:17 +02:00
Documented base.* and core.*
Big job, this documentation lark. Also modified the prototype the packet_is_tlv_null_terminated function, which used to take a Packet instance as well as the TLV, but never used the packet in its implementation.
This commit is contained in:
parent
ebf13ffaa7
commit
2c865a4a37
@ -506,7 +506,7 @@ DWORD command_validate_arguments(Command *command, Packet *packet)
|
||||
switch (tlvMetaType)
|
||||
{
|
||||
case TLV_META_TYPE_STRING:
|
||||
if (packet_is_tlv_null_terminated(packet, ¤t) != ERROR_SUCCESS)
|
||||
if (packet_is_tlv_null_terminated(¤t) != ERROR_SUCCESS)
|
||||
res = ERROR_INVALID_PARAMETER;
|
||||
break;
|
||||
default:
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "core.h"
|
||||
|
||||
/*! @brief Function pointer type that defines the interface for a dispatch handler. */
|
||||
typedef DWORD (*DISPATCH_ROUTINE)(Remote *remote, Packet *packet);
|
||||
typedef DWORD (*DISPATCH_ROUTINE)( Remote *remote, Packet *packet );
|
||||
|
||||
/*! @brief Specifies the maximum number of arguments that are checked/handled
|
||||
* in a request/response packet dispatcher.
|
||||
|
@ -1,26 +1,44 @@
|
||||
/*!
|
||||
* @file core.c
|
||||
* @brief Definitions of core components of the Meterpreter suite.
|
||||
* @details Much of what exists in the core files is used in almost every area
|
||||
* of the Meterpreter code base, and hence it's very important. Don't
|
||||
* change this stuff unless you know what you're doing!
|
||||
*/
|
||||
#include "common.h"
|
||||
|
||||
DWORD packet_find_tlv_buf(Packet *packet, PUCHAR payload, DWORD payloadLength, DWORD index,
|
||||
TlvType type, Tlv *tlv);
|
||||
|
||||
/*! @brief List element that contains packet completion routine details. */
|
||||
typedef struct _PacketCompletionRoutineEntry
|
||||
{
|
||||
LPCSTR requestId;
|
||||
PacketRequestCompletion handler;
|
||||
struct _PacketCompletionRoutineEntry *next;
|
||||
LPCSTR requestId; ///< Id of the request.
|
||||
PacketRequestCompletion handler; ///< Handler to call on completion.
|
||||
struct _PacketCompletionRoutineEntry *next; ///< Pointer to the next compleiont routine entry.
|
||||
} PacketCompletionRoutineEntry;
|
||||
|
||||
/*!
|
||||
* @brief Reference to the list of packet completion routines.
|
||||
* @details This pointer is a singularly-linked list which contains references
|
||||
* to PacketCompletionRouteEntry items, each of which is processed
|
||||
* when packet_call_completion_handlers is invoked.
|
||||
*/
|
||||
PacketCompletionRoutineEntry *packetCompletionRoutineList = NULL;
|
||||
|
||||
/************
|
||||
* Core API *
|
||||
************/
|
||||
|
||||
/*
|
||||
* Transmit a single string to the remote connection with instructions to
|
||||
* print it to the screen or whatever medium has been established.
|
||||
/*!
|
||||
* @brief Print a remote console message.
|
||||
* @details Transmit a single string to the remote connection with instructions
|
||||
* to print it to the screen or whatever medium has been established.
|
||||
* @param remote Pointer to the \c Remote instance that the message should be
|
||||
sent to
|
||||
* @param fmt Format string.
|
||||
* @param ... Varargs that will be printed to the \c fmt format string.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Unable to allocate memory for the request packet.
|
||||
* @retval ERROR_SUCCESS Transmission was successful.
|
||||
*/
|
||||
DWORD send_core_console_write(Remote *remote, LPCSTR fmt, ...)
|
||||
DWORD send_core_console_write( Remote *remote, LPCSTR fmt, ... )
|
||||
{
|
||||
Packet *request = NULL;
|
||||
CHAR buf[8192];
|
||||
@ -58,16 +76,17 @@ DWORD send_core_console_write(Remote *remote, LPCSTR fmt, ...)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
/*!
|
||||
* @todo I have no idea why this is here, need someone else to explain.
|
||||
*/
|
||||
HANDLE core_update_thread_token(Remote *remote, HANDLE token)
|
||||
HANDLE core_update_thread_token( Remote *remote, HANDLE token )
|
||||
{
|
||||
HANDLE temp = NULL;
|
||||
#ifdef _WIN32
|
||||
|
||||
lock_acquire( remote->lock );
|
||||
do {
|
||||
do
|
||||
{
|
||||
temp = remote->hThreadToken;
|
||||
|
||||
// A NULL token resets the state back to the server token
|
||||
@ -78,12 +97,11 @@ HANDLE core_update_thread_token(Remote *remote, HANDLE token)
|
||||
remote->hThreadToken = token;
|
||||
|
||||
// Close the old token if its not one of the two active tokens
|
||||
if(temp && temp != remote->hServerToken && temp != remote->hThreadToken) {
|
||||
if( temp && temp != remote->hServerToken && temp != remote->hThreadToken ) {
|
||||
CloseHandle(temp);
|
||||
}
|
||||
|
||||
} while(0);
|
||||
|
||||
|
||||
lock_release( remote->lock );
|
||||
#else
|
||||
/*
|
||||
@ -93,11 +111,15 @@ HANDLE core_update_thread_token(Remote *remote, HANDLE token)
|
||||
return(token);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the session/station/desktop to be used by multi threaded meterpreter for desktop related operations.
|
||||
* We dont store the handles as it is more convienient to use string,s especially as we cant use the regular API
|
||||
* to break out of sessions.
|
||||
* Note: It is up to the caller to free any station/desktop name provided as internally we use strdup.
|
||||
/*!
|
||||
* @brief Update the session/station/desktop to be used by multi threaded meterpreter for desktop related operations.
|
||||
* @details We dont store the handles as it is more convienient to use strings, especially as we cant use the regular API
|
||||
* to break out of sessions.
|
||||
* @remark It is up to the caller to free any station/desktop name provided as internally we use \c strdup.
|
||||
* @param remote Pointer to the remote connection.
|
||||
* @param dwSessionID ID of the session which contains the window station in \c cpStationName.
|
||||
* @param cpStationName Name of the window station that contains the desktop in \c cpDesktopName.
|
||||
* @param cpDesktopName Name of the desktop to switch to.
|
||||
*/
|
||||
VOID core_update_desktop( Remote * remote, DWORD dwSessionID, char * cpStationName, char * cpDesktopName )
|
||||
{
|
||||
@ -142,14 +164,14 @@ VOID core_update_desktop( Remote * remote, DWORD dwSessionID, char * cpStationNa
|
||||
lock_release( remote->lock );
|
||||
#endif
|
||||
}
|
||||
/*******************
|
||||
* Packet Routines *
|
||||
*******************/
|
||||
|
||||
/*
|
||||
* Create a packet of a given type (request/response) and method.
|
||||
/*!
|
||||
* @brief Create a packet of a given type (request/response) and method.
|
||||
* @param type The TLV type that this packet represents.
|
||||
* @param method TLV method type (can be \c NULL).
|
||||
* @return Pointer to the newly created \c Packet.
|
||||
*/
|
||||
Packet *packet_create(PacketTlvType type, LPCSTR method)
|
||||
Packet *packet_create( PacketTlvType type, LPCSTR method )
|
||||
{
|
||||
Packet *packet = NULL;
|
||||
BOOL success = FALSE;
|
||||
@ -191,11 +213,14 @@ Packet *packet_create(PacketTlvType type, LPCSTR method)
|
||||
return packet;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a response packet from a request, referencing the requestors
|
||||
/*!
|
||||
* @brief Create a response packet from a request.
|
||||
* @details Create a response packet from a request, referencing the requestors
|
||||
* message identifier.
|
||||
* @param request The request \c Packet to build a response for.
|
||||
* @return Pointer to a new \c Packet.
|
||||
*/
|
||||
Packet *packet_create_response(Packet *request)
|
||||
Packet *packet_create_response( Packet *request )
|
||||
{
|
||||
Packet *response = NULL;
|
||||
Tlv method, requestId;
|
||||
@ -240,8 +265,9 @@ Packet *packet_create_response(Packet *request)
|
||||
return response;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the packet context and the payload buffer
|
||||
/*!
|
||||
* @brief Destroy the packet context and the payload buffer.
|
||||
* @param packet Pointer to the \c Packet to destroy.
|
||||
*/
|
||||
VOID packet_destroy( Packet * packet )
|
||||
{
|
||||
@ -279,28 +305,46 @@ VOID packet_destroy( Packet * packet )
|
||||
free( packet );
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a TLV as a string, including the null terminator.
|
||||
/*!
|
||||
* @brief Add a string value TLV to a packet, including the \c NULL terminator.
|
||||
* @param packet Pointer to the packet to add the value to.
|
||||
* @param type TLV type for the value.
|
||||
* @param str Pointer to the string value to add to the packet.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
|
||||
*/
|
||||
DWORD packet_add_tlv_string(Packet *packet, TlvType type, LPCSTR str)
|
||||
DWORD packet_add_tlv_string( Packet *packet, TlvType type, LPCSTR str )
|
||||
{
|
||||
return packet_add_tlv_raw(packet, type, (PUCHAR)str, (DWORD)strlen(str) + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a TLV as a string, including the null terminator.
|
||||
/*!
|
||||
* @brief Add a unsigned integer value TLV to a packet.
|
||||
* @param packet Pointer to the packet to add the value to.
|
||||
* @param type TLV type for the value.
|
||||
* @param val The value to add to the packet.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
|
||||
*/
|
||||
DWORD packet_add_tlv_uint(Packet *packet, TlvType type, UINT val)
|
||||
DWORD packet_add_tlv_uint( Packet *packet, TlvType type, UINT val )
|
||||
{
|
||||
val = htonl(val);
|
||||
|
||||
return packet_add_tlv_raw(packet, type, (PUCHAR)&val, sizeof(val));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a TLV as a QWORD.
|
||||
/*!
|
||||
* @brief Add a quad-work value TLV to a packet.
|
||||
* @param packet Pointer to the packet to add the value to.
|
||||
* @param type TLV type for the value.
|
||||
* @param val The value to add to the packet.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
|
||||
*/
|
||||
DWORD packet_add_tlv_qword(Packet *packet, TlvType type, QWORD val )
|
||||
DWORD packet_add_tlv_qword( Packet *packet, TlvType type, QWORD val )
|
||||
{
|
||||
val = htonq( val );
|
||||
|
||||
@ -308,18 +352,32 @@ DWORD packet_add_tlv_qword(Packet *packet, TlvType type, QWORD val )
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add a TLV as a bool.
|
||||
/*!
|
||||
* @brief Add a boolean value TLV to a packet.
|
||||
* @param packet Pointer to the packet to add the value to.
|
||||
* @param type TLV type for the value.
|
||||
* @param val The value to add to the packet.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
|
||||
*/
|
||||
DWORD packet_add_tlv_bool(Packet *packet, TlvType type, BOOL val)
|
||||
{
|
||||
return packet_add_tlv_raw(packet, type, (PUCHAR)&val, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a TLV group. A TLV group is a TLV that contains multiple sub-TLVs
|
||||
/*!
|
||||
* @brief Add a group TLV to a packet.
|
||||
* @details A TLV group is a TLV that contains multiple sub-TLVs.
|
||||
* @param packet Pointer to the packet to add the value to.
|
||||
* @param type TLV type for the value.
|
||||
* @param entries Pointer to the array of TLV entries to add.
|
||||
* @param numEntries Count of the number of TLV entries in the \c entries array.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
|
||||
*/
|
||||
DWORD packet_add_tlv_group(Packet *packet, TlvType type, Tlv *entries, DWORD numEntries)
|
||||
DWORD packet_add_tlv_group( Packet *packet, TlvType type, Tlv *entries, DWORD numEntries )
|
||||
{
|
||||
DWORD totalSize = 0,
|
||||
offset = 0,
|
||||
@ -369,23 +427,37 @@ DWORD packet_add_tlv_group(Packet *packet, TlvType type, Tlv *entries, DWORD num
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an array of TLVs
|
||||
/*!
|
||||
* @brief Add an array of TLVs to a packet.
|
||||
* @param packet Pointer to the packet to add the values to.
|
||||
* @param entries Pointer to the array of TLV entries to add.
|
||||
* @param numEntries Count of the number of TLV entries in the \c entries array.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
|
||||
*/
|
||||
DWORD packet_add_tlvs(Packet *packet, Tlv *entries, DWORD numEntries)
|
||||
DWORD packet_add_tlvs( Packet *packet, Tlv *entries, DWORD numEntries )
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
for (index = 0; index < numEntries; index++)
|
||||
packet_add_tlv_raw(packet, entries[index].header.type, entries[index].buffer, entries[index].header.length);
|
||||
packet_add_tlv_raw(packet, (TlvType)entries[index].header.type, entries[index].buffer, entries[index].header.length);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an arbitrary TLV whose data is to be compressed with zlib.
|
||||
/*!
|
||||
* @brief Add a raw value TLV to a packet, with compression.
|
||||
* @details The value given in the \c buf parameter will be compressed with zlib.
|
||||
* @param packet Pointer to the packet to add the value to.
|
||||
* @param type TLV type for the value.
|
||||
* @param buf Pointer to the data that is to be compressed and added.
|
||||
* @param length Number of bytes in \c buf to compress.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
|
||||
*/
|
||||
DWORD packet_add_tlv_raw_compressed(Packet *packet, TlvType type, LPVOID buf, DWORD length)
|
||||
DWORD packet_add_tlv_raw_compressed( Packet *packet, TlvType type, LPVOID buf, DWORD length )
|
||||
{
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
DWORD headerLength = sizeof( TlvHeader );
|
||||
@ -446,10 +518,18 @@ DWORD packet_add_tlv_raw_compressed(Packet *packet, TlvType type, LPVOID buf, DW
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an arbitrary TLV
|
||||
/*!
|
||||
* @brief Add an arbitrary raw value TLV to a packet.
|
||||
* @details The value given in the \c buf parameter will _not_ be compressed.
|
||||
* @param packet Pointer to the packet to add the value to.
|
||||
* @param type TLV type for the value.
|
||||
* @param buf Pointer to the data that is to be added.
|
||||
* @param length Number of bytes in \c buf to add.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
|
||||
*/
|
||||
DWORD packet_add_tlv_raw(Packet *packet, TlvType type, LPVOID buf, DWORD length)
|
||||
DWORD packet_add_tlv_raw( Packet *packet, TlvType type, LPVOID buf, DWORD length )
|
||||
{
|
||||
DWORD headerLength = sizeof(TlvHeader);
|
||||
DWORD realLength = length + headerLength;
|
||||
@ -462,9 +542,9 @@ DWORD packet_add_tlv_raw(Packet *packet, TlvType type, LPVOID buf, DWORD length)
|
||||
|
||||
// Allocate/Reallocate the packet's payload
|
||||
if (packet->payload)
|
||||
newPayload = (PUCHAR)realloc(packet->payload, newPayloadLength);
|
||||
newPayload = (PUCHAR)realloc( packet->payload, newPayloadLength );
|
||||
else
|
||||
newPayload = (PUCHAR)malloc(newPayloadLength);
|
||||
newPayload = (PUCHAR)malloc( newPayloadLength );
|
||||
|
||||
if (!newPayload)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
@ -473,7 +553,7 @@ DWORD packet_add_tlv_raw(Packet *packet, TlvType type, LPVOID buf, DWORD length)
|
||||
((LPDWORD)(newPayload + packet->payloadLength))[0] = htonl(realLength);
|
||||
((LPDWORD)(newPayload + packet->payloadLength))[1] = htonl((DWORD)type);
|
||||
|
||||
memcpy(newPayload + packet->payloadLength + headerLength, buf, length);
|
||||
memcpy( newPayload + packet->payloadLength + headerLength, buf, length );
|
||||
|
||||
// Update the header length and payload length
|
||||
packet->header.length = htonl(ntohl(packet->header.length) + realLength);
|
||||
@ -483,10 +563,17 @@ DWORD packet_add_tlv_raw(Packet *packet, TlvType type, LPVOID buf, DWORD length)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks to see if a tlv is null terminated
|
||||
/*!
|
||||
* @brief Check if a TLV is NULL-terminated.
|
||||
* @details The function checks the data within the range of bytes specified by
|
||||
* the \c length property of the TLV \c header.
|
||||
* @param tlv Pointer to the TLV to check.
|
||||
* @return Indication of whether the TLV is terminated with a \c NULL byte or not.
|
||||
* @retval ERROR_SUCCESS A \c NULL byte is present.
|
||||
* @retval ERROR_NOT_FOUND No \c NULL byte is present.
|
||||
* @sa TlvHeader
|
||||
*/
|
||||
DWORD packet_is_tlv_null_terminated(Packet *packet, Tlv *tlv)
|
||||
DWORD packet_is_tlv_null_terminated( Tlv *tlv )
|
||||
{
|
||||
if ((tlv->header.length) && (tlv->buffer[tlv->header.length - 1] != 0))
|
||||
return ERROR_NOT_FOUND;
|
||||
@ -494,84 +581,132 @@ DWORD packet_is_tlv_null_terminated(Packet *packet, Tlv *tlv)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the type of the packet
|
||||
/*!
|
||||
* @brief Get the TLV type of the packet.
|
||||
* @param packet Pointer to the packet to get the type from.
|
||||
* @return \c PacketTlvType for the given \c Packet.
|
||||
*/
|
||||
PacketTlvType packet_get_type(Packet *packet)
|
||||
PacketTlvType packet_get_type( Packet *packet )
|
||||
{
|
||||
return (PacketTlvType)ntohl(packet->header.type);
|
||||
return (PacketTlvType)ntohl( packet->header.type );
|
||||
}
|
||||
|
||||
TlvMetaType packet_get_tlv_meta(Packet *packet, Tlv *tlv)
|
||||
/*!
|
||||
* @brief Get the TLV meta-type of the packet.
|
||||
* @param packet Pointer to the packet to get the meta-type from.
|
||||
* @return \c TlvMetaType for the given \c Packet.
|
||||
*/
|
||||
TlvMetaType packet_get_tlv_meta( Packet *packet, Tlv *tlv )
|
||||
{
|
||||
return TLV_META_TYPE_MASK(tlv->header.type);
|
||||
return TLV_META_TYPE_MASK( tlv->header.type );
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the TLV of the given type
|
||||
/*!
|
||||
* @brief Get a TLV of a given type from the packet.
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param type Type of TLV to get.
|
||||
* @param tlv Pointer to the TLV that will receive the data.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_FOUND Unable to find the TLV.
|
||||
*/
|
||||
DWORD packet_get_tlv(Packet *packet, TlvType type, Tlv *tlv)
|
||||
DWORD packet_get_tlv( Packet *packet, TlvType type, Tlv *tlv )
|
||||
{
|
||||
return packet_enum_tlv(packet, 0, type, tlv);
|
||||
return packet_enum_tlv( packet, 0, type, tlv );
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a TLV as a string
|
||||
/*!
|
||||
* @brief Get a string TLV from the packet.
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param type Type of TLV to get.
|
||||
* @param tlv Pointer to the TLV that will receive the data.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_FOUND Unable to find the TLV or the string
|
||||
* value is not NULL-terminated.
|
||||
*/
|
||||
DWORD packet_get_tlv_string(Packet *packet, TlvType type, Tlv *tlv)
|
||||
DWORD packet_get_tlv_string( Packet *packet, TlvType type, Tlv *tlv )
|
||||
{
|
||||
DWORD res;
|
||||
|
||||
if ((res = packet_get_tlv(packet, type, tlv)) == ERROR_SUCCESS)
|
||||
res = packet_is_tlv_null_terminated(packet, tlv);
|
||||
if ((res = packet_get_tlv( packet, type, tlv )) == ERROR_SUCCESS)
|
||||
res = packet_is_tlv_null_terminated( tlv );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumerate a TLV group (a TLV that consists other multiple sub-TLVs) and
|
||||
* finds the first match of a given type, if it exists.
|
||||
/*!
|
||||
* @brief Get a TLV of a given type from a group TLV in the packet.
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param group Pointer to the group TLV to get the value from.
|
||||
* @param type Type of TLV to get.
|
||||
* @param tlv Pointer to the TLV that will receive the data.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_FOUND Unable to find the TLV.
|
||||
*/
|
||||
DWORD packet_get_tlv_group_entry(Packet *packet, Tlv *group, TlvType type, Tlv *entry)
|
||||
DWORD packet_get_tlv_group_entry( Packet *packet, Tlv *group, TlvType type, Tlv *entry )
|
||||
{
|
||||
return packet_find_tlv_buf( packet, group->buffer, group->header.length, 0, type, entry);
|
||||
return packet_find_tlv_buf( packet, group->buffer, group->header.length, 0, type, entry );
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumerate a TLV, optionally of a specified typed.
|
||||
/*!
|
||||
* @brief Enumerate a TLV (with the option of constraining its type).
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param type Type of TLV to get (optional).
|
||||
* @param tlv Pointer to the TLV that will receive the data.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_FOUND Unable to find the TLV.
|
||||
*/
|
||||
DWORD packet_enum_tlv(Packet *packet, DWORD index, TlvType type, Tlv *tlv)
|
||||
DWORD packet_enum_tlv( Packet *packet, DWORD index, TlvType type, Tlv *tlv )
|
||||
{
|
||||
return packet_find_tlv_buf( packet, packet->payload, packet->payloadLength, index, type, tlv);
|
||||
return packet_find_tlv_buf( packet, packet->payload, packet->payloadLength, index, type, tlv );
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the value of a string TLV
|
||||
/*!
|
||||
* @brief Get the string value of a TLV.
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param type Type of TLV to get (optional).
|
||||
* @return Pointer to the string value, if found.
|
||||
* @retval NULL The string value was not found in the TLV.
|
||||
* @retval Non-NULL Pointer to the string value.
|
||||
*/
|
||||
PCHAR packet_get_tlv_value_string(Packet *packet, TlvType type)
|
||||
PCHAR packet_get_tlv_value_string( Packet *packet, TlvType type )
|
||||
{
|
||||
Tlv stringTlv;
|
||||
PCHAR string = NULL;
|
||||
|
||||
if (packet_get_tlv_string(packet, type, &stringTlv) == ERROR_SUCCESS)
|
||||
if (packet_get_tlv_string( packet, type, &stringTlv ) == ERROR_SUCCESS)
|
||||
string = (PCHAR)stringTlv.buffer;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the value of a UINT TLV
|
||||
/*!
|
||||
* @brief Get the unsigned int value of a TLV.
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param type Type of TLV to get (optional).
|
||||
* @return The value found in the TLV.
|
||||
* @todo On failure, 0 is returned. We need to make sure this is the right
|
||||
* thing to do because 0 might also be a valid value.
|
||||
*/
|
||||
UINT packet_get_tlv_value_uint(Packet *packet, TlvType type)
|
||||
UINT packet_get_tlv_value_uint( Packet *packet, TlvType type )
|
||||
{
|
||||
Tlv uintTlv;
|
||||
|
||||
if ((packet_get_tlv(packet, type, &uintTlv) != ERROR_SUCCESS) ||(uintTlv.header.length < sizeof(DWORD)))
|
||||
if ((packet_get_tlv( packet, type, &uintTlv ) != ERROR_SUCCESS) || (uintTlv.header.length < sizeof(DWORD)))
|
||||
return 0;
|
||||
|
||||
return ntohl(*(LPDWORD)uintTlv.buffer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the raw value of a TLV.
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param type Type of TLV to get (optional).
|
||||
* @return The value found in the TLV.
|
||||
*/
|
||||
BYTE * packet_get_tlv_value_raw( Packet * packet, TlvType type )
|
||||
{
|
||||
Tlv tlv;
|
||||
@ -582,10 +717,15 @@ BYTE * packet_get_tlv_value_raw( Packet * packet, TlvType type )
|
||||
return tlv.buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the value of a QWORD TLV
|
||||
/*!
|
||||
* @brief Get the quad-word value of a TLV.
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param type Type of TLV to get (optional).
|
||||
* @return The value found in the TLV.
|
||||
* @todo On failure, 0 is returned. We need to make sure this is the right
|
||||
* thing to do because 0 might also be a valid value.
|
||||
*/
|
||||
QWORD packet_get_tlv_value_qword(Packet *packet, TlvType type)
|
||||
QWORD packet_get_tlv_value_qword( Packet *packet, TlvType type )
|
||||
{
|
||||
Tlv qwordTlv;
|
||||
|
||||
@ -595,25 +735,38 @@ QWORD packet_get_tlv_value_qword(Packet *packet, TlvType type)
|
||||
return ntohq( *(QWORD *)qwordTlv.buffer );
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the value of a bool TLV
|
||||
/*!
|
||||
* @brief Get the boolean value of a TLV.
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param type Type of TLV to get (optional).
|
||||
* @return The value found in the TLV.
|
||||
* @todo On failure, FALSE is returned. We need to make sure this is the right
|
||||
* thing to do because FALSE might also be a valid value.
|
||||
*/
|
||||
BOOL packet_get_tlv_value_bool(Packet *packet, TlvType type)
|
||||
BOOL packet_get_tlv_value_bool( Packet *packet, TlvType type )
|
||||
{
|
||||
Tlv boolTlv;
|
||||
BOOL val = FALSE;
|
||||
|
||||
if (packet_get_tlv(packet, type, &boolTlv) == ERROR_SUCCESS)
|
||||
if (packet_get_tlv( packet, type, &boolTlv ) == ERROR_SUCCESS)
|
||||
val = (BOOL)(*(PCHAR)boolTlv.buffer);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an exception to a packet
|
||||
/*!
|
||||
* @brief Add an exception to a packet.
|
||||
* @details When adding an exception, both a TLV_EXCEPTION_CODE and TLV_EXCEPTION_STRING
|
||||
* are added to the packet.
|
||||
* @param packet Pointer to the packet to add the detail to.
|
||||
* @param code Exception code.
|
||||
* @param fmt Form string for the exception string.
|
||||
* @param ... Varargs for the format string.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Unable to allocate memory for the request packet.
|
||||
* @retval ERROR_SUCCESS Transmission was successful.
|
||||
*/
|
||||
DWORD packet_add_exception(Packet *packet, DWORD code,
|
||||
PCHAR fmt, ...)
|
||||
DWORD packet_add_exception( Packet *packet, DWORD code, PCHAR fmt, ... )
|
||||
{
|
||||
DWORD codeNbo = htonl(code);
|
||||
char buf[8192];
|
||||
@ -636,21 +789,40 @@ DWORD packet_add_exception(Packet *packet, DWORD code,
|
||||
entries[1].buffer = (PUCHAR)buf;
|
||||
|
||||
// Add the TLV group, or try to at least.
|
||||
return packet_add_tlv_group(packet, TLV_TYPE_EXCEPTION, entries, 2);
|
||||
return packet_add_tlv_group( packet, TLV_TYPE_EXCEPTION, entries, 2 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the result code from the packet
|
||||
/*!
|
||||
* @brief Get the result code from the packet
|
||||
* @param packet Pointer to the packet to get thget the result code from
|
||||
* @return The result code.
|
||||
*/
|
||||
DWORD packet_get_result(Packet *packet)
|
||||
DWORD packet_get_result( Packet *packet )
|
||||
{
|
||||
return packet_get_tlv_value_uint(packet, TLV_TYPE_RESULT);
|
||||
return packet_get_tlv_value_uint( packet, TLV_TYPE_RESULT );
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumerate TLV entries in a buffer until hitting a given index (optionally for a given type as well).
|
||||
*/
|
||||
DWORD packet_find_tlv_buf( Packet *packet, PUCHAR payload, DWORD payloadLength, DWORD index, TlvType type, Tlv *tlv)
|
||||
/*!
|
||||
* @brief Enumerate TLV entries until hitting a given index or type.
|
||||
* @details This function will iterate through the given payload until one of the following conditions is true:
|
||||
* - The end of the payload is encountered
|
||||
* - The specified index is reached
|
||||
* - A TLV of the specified type is reached
|
||||
*
|
||||
* If the first condition is met, the function returns with a failure.
|
||||
* @param packet Pointer to the packet to get the TLV from.
|
||||
* @param payload Pointer to the payload to parse.
|
||||
* @param index Index of the TLV entry to find (optional).
|
||||
* @param type Type of TLV to get (optional).
|
||||
* @param tlv Pointer to the TLV that will receive the data.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_SUCCESS The operation completed successfully.
|
||||
* @retval ERROR_NOT_FOUND Unable to find the TLV.
|
||||
*/
|
||||
DWORD packet_find_tlv_buf( Packet *packet, PUCHAR payload, DWORD payloadLength, DWORD index, TlvType type, Tlv *tlv )
|
||||
{
|
||||
DWORD currentIndex = 0;
|
||||
DWORD offset = 0, length = 0;
|
||||
@ -759,14 +931,13 @@ DWORD packet_find_tlv_buf( Packet *packet, PUCHAR payload, DWORD payloadLength,
|
||||
return (found) ? ERROR_SUCCESS : ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Completion Routines *
|
||||
***********************/
|
||||
|
||||
/*
|
||||
* Add a completion routine for a given request identifier
|
||||
/*!
|
||||
* @brief Add a completion routine for a given request identifier.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_NOT_ENOUGH_MEMORY Unable to allocate memory for the \c PacketCompletionRouteEntry instance.
|
||||
* @retval ERROR_SUCCESS Addition was successful.
|
||||
*/
|
||||
DWORD packet_add_completion_handler(LPCSTR requestId, PacketRequestCompletion *completion)
|
||||
DWORD packet_add_completion_handler( LPCSTR requestId, PacketRequestCompletion *completion )
|
||||
{
|
||||
PacketCompletionRoutineEntry *entry;
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
@ -774,17 +945,17 @@ DWORD packet_add_completion_handler(LPCSTR requestId, PacketRequestCompletion *c
|
||||
do
|
||||
{
|
||||
// Allocate the entry
|
||||
if (!(entry = (PacketCompletionRoutineEntry *)malloc(sizeof(PacketCompletionRoutineEntry))))
|
||||
if (!(entry = (PacketCompletionRoutineEntry *)malloc( sizeof(PacketCompletionRoutineEntry) )))
|
||||
{
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy the completion routine information
|
||||
memcpy(&entry->handler, completion, sizeof(PacketRequestCompletion));
|
||||
memcpy( &entry->handler, completion, sizeof(PacketRequestCompletion) );
|
||||
|
||||
// Copy the request identifier
|
||||
if (!(entry->requestId = _strdup(requestId)))
|
||||
if (!(entry->requestId = _strdup( requestId )))
|
||||
{
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
@ -803,25 +974,31 @@ DWORD packet_add_completion_handler(LPCSTR requestId, PacketRequestCompletion *c
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the register completion handler(s) for the given request identifier.
|
||||
*/
|
||||
DWORD packet_call_completion_handlers(Remote *remote, Packet *response,LPCSTR requestId)
|
||||
/*!
|
||||
* @brief Call the register completion handler(s) for the given request identifier.
|
||||
* @details Only those handlers that match the given request are executed.
|
||||
* @param remote Pointer to the \c Remote instance for this call.
|
||||
* @param response Pointer to the response \c Packet.
|
||||
* @param requestId ID of the request to execute the completion handlers of.
|
||||
* @return Indication of success or failure.
|
||||
* @retval ERROR_NOT_FOUND Unable to find any matching completion handlers for the request.
|
||||
* @retval ERROR_SUCCESS Execution was successful.
|
||||
*/
|
||||
DWORD packet_call_completion_handlers( Remote *remote, Packet *response, LPCSTR requestId )
|
||||
{
|
||||
PacketCompletionRoutineEntry *current;
|
||||
DWORD result = packet_get_result(response);
|
||||
DWORD result = packet_get_result( response );
|
||||
DWORD matches = 0;
|
||||
Tlv methodTlv;
|
||||
LPCSTR method = NULL;
|
||||
|
||||
// Get the method associated with this packet
|
||||
if (packet_get_tlv_string(response, TLV_TYPE_METHOD,
|
||||
&methodTlv) == ERROR_SUCCESS)
|
||||
if (packet_get_tlv_string(response, TLV_TYPE_METHOD, &methodTlv) == ERROR_SUCCESS)
|
||||
method = (LPCSTR)methodTlv.buffer;
|
||||
|
||||
// Enumerate the completion routine list
|
||||
for (current = packetCompletionRoutineList;
|
||||
current;
|
||||
current = current->next)
|
||||
for (current = packetCompletionRoutineList; current; current = current->next)
|
||||
{
|
||||
// Does the request id of the completion entry match the packet's request
|
||||
// id?
|
||||
@ -842,10 +1019,12 @@ DWORD packet_call_completion_handlers(Remote *remote, Packet *response,LPCSTR re
|
||||
return (matches > 0) ? ERROR_SUCCESS : ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove one or more completion handlers for the given request identifier
|
||||
/*!
|
||||
* @brief Remove a set of completion routine handlers for a given request identifier.
|
||||
* @param requestId ID of the request.
|
||||
* @return \c ERROR_SUCCESS is always returned.
|
||||
*/
|
||||
DWORD packet_remove_completion_handler(LPCSTR requestId)
|
||||
DWORD packet_remove_completion_handler( LPCSTR requestId )
|
||||
{
|
||||
PacketCompletionRoutineEntry *current, *next, *prev;
|
||||
|
||||
@ -873,10 +1052,16 @@ DWORD packet_remove_completion_handler(LPCSTR requestId)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmit and destroy a packet
|
||||
/*!
|
||||
* @brief Transmit _and_ destroy a packet.
|
||||
* @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 simply proxies to \c packet_transmit_via_ssl or \c packet_transmit_via_http
|
||||
* depending on what the remote transport type is.
|
||||
*/
|
||||
DWORD packet_transmit(Remote *remote, Packet *packet, PacketRequestCompletion *completion)
|
||||
DWORD packet_transmit( Remote *remote, Packet *packet, PacketRequestCompletion *completion )
|
||||
{
|
||||
if (remote->transport == METERPRETER_TRANSPORT_SSL) {
|
||||
return packet_transmit_via_ssl(remote, packet, completion);
|
||||
@ -887,10 +1072,15 @@ DWORD packet_transmit(Remote *remote, Packet *packet, PacketRequestCompletion *c
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmit and destroy a packet over SSL
|
||||
/*!
|
||||
* @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)
|
||||
DWORD packet_transmit_via_ssl( Remote *remote, Packet *packet, PacketRequestCompletion *completion )
|
||||
{
|
||||
CryptoContext *crypto;
|
||||
Tlv requestId;
|
||||
@ -1006,10 +1196,14 @@ DWORD packet_transmit_via_ssl(Remote *remote, Packet *packet, PacketRequestCompl
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Transmit and destroy a packet over HTTP(S)
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
DWORD packet_transmit_via_http(Remote *remote, Packet *packet, PacketRequestCompletion *completion)
|
||||
DWORD packet_transmit_via_http( Remote *remote, Packet *packet, PacketRequestCompletion *completion )
|
||||
{
|
||||
CryptoContext *crypto;
|
||||
Tlv requestId;
|
||||
@ -1096,11 +1290,16 @@ DWORD packet_transmit_via_http(Remote *remote, Packet *packet, PacketRequestComp
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transmit and destroy a packet over HTTP(S)
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
DWORD packet_transmit_via_http_wininet(Remote *remote, Packet *packet, PacketRequestCompletion *completion) {
|
||||
/*!
|
||||
* @brief Windows-specific function to 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.
|
||||
* @remark This function is not available on POSIX.
|
||||
*/
|
||||
DWORD packet_transmit_via_http_wininet( Remote *remote, Packet *packet, PacketRequestCompletion *completion ) {
|
||||
DWORD res = 0;
|
||||
HINTERNET hReq;
|
||||
BOOL hRes;
|
||||
@ -1157,10 +1356,14 @@ DWORD packet_transmit_via_http_wininet(Remote *remote, Packet *packet, PacketReq
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Transmits a response with nothing other than a result code in it
|
||||
/*!
|
||||
* @brief Transmit a response with just a result code to the remote endpoint.
|
||||
* @param remote Pointer to the \c Remote instance.
|
||||
* @param packet Pointer to the \c Packet that is to be sent.
|
||||
* @param res Result code to return.
|
||||
* @return An indication of the result of processing the transmission request.
|
||||
*/
|
||||
DWORD packet_transmit_empty_response(Remote *remote, Packet *packet, DWORD res)
|
||||
DWORD packet_transmit_empty_response( Remote *remote, Packet *packet, DWORD res )
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
|
||||
@ -1174,10 +1377,13 @@ DWORD packet_transmit_empty_response(Remote *remote, Packet *packet, DWORD res)
|
||||
return packet_transmit(remote, response, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a new packet
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
DWORD packet_receive(Remote *remote, Packet **packet)
|
||||
DWORD packet_receive( Remote *remote, Packet **packet )
|
||||
{
|
||||
DWORD headerBytes = 0, payloadBytesLeft = 0, res;
|
||||
CryptoContext *crypto = NULL;
|
||||
@ -1191,11 +1397,9 @@ DWORD packet_receive(Remote *remote, Packet **packet)
|
||||
#ifdef _UNIX
|
||||
int local_error = -1;
|
||||
#endif
|
||||
|
||||
|
||||
if (remote->transport == METERPRETER_TRANSPORT_HTTP || remote->transport == METERPRETER_TRANSPORT_HTTPS)
|
||||
return packet_receive_via_http(remote, packet);
|
||||
|
||||
return packet_receive_via_http( remote, packet );
|
||||
|
||||
lock_acquire( remote->lock );
|
||||
|
||||
@ -1231,11 +1435,11 @@ DWORD packet_receive(Remote *remote, Packet **packet)
|
||||
// Initialize the header
|
||||
header.length = header.length;
|
||||
header.type = header.type;
|
||||
payloadLength = ntohl(header.length) - sizeof(TlvHeader);
|
||||
payloadLength = ntohl( header.length ) - sizeof(TlvHeader);
|
||||
payloadBytesLeft = payloadLength;
|
||||
|
||||
// Allocate the payload
|
||||
if (!(payload = (PUCHAR)malloc(payloadLength)))
|
||||
if (!(payload = (PUCHAR)malloc( payloadLength )))
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
break;
|
||||
@ -1244,7 +1448,7 @@ DWORD packet_receive(Remote *remote, Packet **packet)
|
||||
// Read the payload
|
||||
while (payloadBytesLeft > 0)
|
||||
{
|
||||
if ((bytesRead = SSL_read(remote->ssl, payload + payloadLength - payloadBytesLeft, payloadBytesLeft)) <= 0)
|
||||
if ((bytesRead = SSL_read( remote->ssl, payload + payloadLength - payloadBytesLeft, payloadBytesLeft )) <= 0)
|
||||
{
|
||||
|
||||
if (GetLastError() == WSAEWOULDBLOCK)
|
||||
@ -1269,7 +1473,7 @@ DWORD packet_receive(Remote *remote, Packet **packet)
|
||||
break;
|
||||
|
||||
// Allocate a packet structure
|
||||
if (!(localPacket = (Packet *)malloc(sizeof(Packet))))
|
||||
if (!(localPacket = (Packet *)malloc( sizeof(Packet) )))
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
break;
|
||||
@ -1279,15 +1483,15 @@ DWORD packet_receive(Remote *remote, Packet **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))
|
||||
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)
|
||||
if ((res = crypto->handlers.decrypt( crypto, payload, payloadLength,&payload, &payloadLength )) != ERROR_SUCCESS)
|
||||
{
|
||||
SetLastError(res);
|
||||
break;
|
||||
@ -1311,12 +1515,12 @@ DWORD packet_receive(Remote *remote, Packet **packet)
|
||||
res = GetLastError();
|
||||
|
||||
// Cleanup on failure
|
||||
if (res != ERROR_SUCCESS)
|
||||
if ( res != ERROR_SUCCESS )
|
||||
{
|
||||
if (payload)
|
||||
free(payload);
|
||||
free( payload );
|
||||
if (localPacket)
|
||||
free(localPacket);
|
||||
free( localPacket );
|
||||
}
|
||||
|
||||
lock_release( remote->lock );
|
||||
@ -1326,10 +1530,14 @@ DWORD packet_receive(Remote *remote, Packet **packet)
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Receive a new packet over HTTP using WinInet
|
||||
/*!
|
||||
* @brief Windows-specific function to receive a new packet via WinInet.
|
||||
* @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.
|
||||
*/
|
||||
DWORD packet_receive_http_via_wininet(Remote *remote, Packet **packet) {
|
||||
DWORD packet_receive_http_via_wininet( Remote *remote, Packet **packet ) {
|
||||
|
||||
DWORD headerBytes = 0, payloadBytesLeft = 0, res;
|
||||
CryptoContext *crypto = NULL;
|
||||
@ -1355,7 +1563,7 @@ DWORD packet_receive_http_via_wininet(Remote *remote, Packet **packet) {
|
||||
flags |= INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
|
||||
}
|
||||
dprintf("[PACKET RECEIVE] HttpOpenRequest");
|
||||
hReq = HttpOpenRequest(remote->hConnection, "POST", remote->uri, NULL, NULL, NULL, flags, 0);
|
||||
hReq = HttpOpenRequest( remote->hConnection, "POST", remote->uri, NULL, NULL, NULL, flags, 0 );
|
||||
|
||||
if (hReq == NULL) {
|
||||
dprintf("[PACKET RECEIVE] Failed HttpOpenRequest: %d", GetLastError());
|
||||
@ -1511,11 +1719,15 @@ DWORD packet_receive_http_via_wininet(Remote *remote, Packet **packet) {
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Receive a new packet over HTTP
|
||||
/*!
|
||||
* @brief Windows-specific function to receive a new packet via WinInet.
|
||||
* @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 just a proxy which calls \c packet_receive_http_via_wininet
|
||||
* and doesn't yet have a POSIX implementation.
|
||||
*/
|
||||
|
||||
DWORD packet_receive_via_http(Remote *remote, Packet **packet)
|
||||
DWORD packet_receive_via_http( Remote *remote, Packet **packet )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return packet_receive_http_via_wininet(remote, packet);
|
||||
|
@ -53,9 +53,13 @@ typedef enum
|
||||
/*! @brief Meta TLV argument type representing a flag set/mask value. */
|
||||
#define TLV_META_TYPE_MASK(x) ((x) & 0xffff0000)
|
||||
|
||||
/*! @brief Base value for reserved TLV definitions. */
|
||||
#define TLV_RESERVED 0
|
||||
/*! @brief Base value for TLV definitions that are part of extensions. */
|
||||
#define TLV_EXTENSIONS 20000
|
||||
/*! @brief Base value for user TLV definitions. */
|
||||
#define TLV_USER 40000
|
||||
/*! @brief Base value for temporary TLV definitions. */
|
||||
#define TLV_TEMP 60000
|
||||
|
||||
/*!
|
||||
@ -95,7 +99,7 @@ typedef DWORD TlvMetaType;
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
TLV_TYPE_ANY = TLV_VALUE(TLV_META_TYPE_NONE, 0),
|
||||
TLV_TYPE_ANY = TLV_VALUE(TLV_META_TYPE_NONE, 0), ///< Represents an undefined/arbitrary value.
|
||||
TLV_TYPE_METHOD = TLV_VALUE(TLV_META_TYPE_STRING, 1), ///< Represents a method/function name value.
|
||||
TLV_TYPE_REQUEST_ID = TLV_VALUE(TLV_META_TYPE_STRING, 2), ///< Represents a request identifier value.
|
||||
TLV_TYPE_EXCEPTION = TLV_VALUE(TLV_META_TYPE_GROUP, 3), ///< Represents an exception value.
|
||||
@ -125,8 +129,8 @@ typedef enum
|
||||
TLV_TYPE_SEEK_POS = TLV_VALUE(TLV_META_TYPE_UINT, 72),
|
||||
|
||||
// Grouped identifiers
|
||||
TLV_TYPE_EXCEPTION_CODE = TLV_VALUE(TLV_META_TYPE_UINT, 300),
|
||||
TLV_TYPE_EXCEPTION_STRING = TLV_VALUE(TLV_META_TYPE_STRING, 301),
|
||||
TLV_TYPE_EXCEPTION_CODE = TLV_VALUE(TLV_META_TYPE_UINT, 300), ///< Represents an exception code value (unsigned in).
|
||||
TLV_TYPE_EXCEPTION_STRING = TLV_VALUE(TLV_META_TYPE_STRING, 301), ///< Represents an exception message value (string).
|
||||
|
||||
// Library loading
|
||||
TLV_TYPE_LIBRARY_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 400), ///< Represents a path to the library to be loaded (string).
|
||||
@ -141,9 +145,9 @@ typedef enum
|
||||
TLV_TYPE_CIPHER_NAME = TLV_VALUE(TLV_META_TYPE_STRING, 500), ///< Represents the name of a cipher.
|
||||
TLV_TYPE_CIPHER_PARAMETERS = TLV_VALUE(TLV_META_TYPE_GROUP, 501), ///< Represents parameters for a cipher.
|
||||
|
||||
TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000),
|
||||
TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000),
|
||||
TLV_TYPE_TEMP = TLV_VALUE(TLV_META_TYPE_COMPLEX, 60000),
|
||||
TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000), ///< Represents an extension value.
|
||||
TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000), ///< Represents a user value.
|
||||
TLV_TYPE_TEMP = TLV_VALUE(TLV_META_TYPE_COMPLEX, 60000), ///< Represents a temporary value.
|
||||
} TlvType;
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -212,7 +216,7 @@ LINKAGE DWORD packet_add_tlv_bool(Packet *packet, TlvType type, BOOL val);
|
||||
LINKAGE DWORD packet_add_tlv_group(Packet *packet, TlvType type, Tlv *entries, DWORD numEntries);
|
||||
LINKAGE DWORD packet_add_tlvs(Packet *packet, Tlv *entries, DWORD numEntries);
|
||||
LINKAGE DWORD packet_add_tlv_raw(Packet *packet, TlvType type, LPVOID buf, DWORD length);
|
||||
LINKAGE DWORD packet_is_tlv_null_terminated(Packet *packet, Tlv *tlv);
|
||||
LINKAGE DWORD packet_is_tlv_null_terminated(Tlv *tlv);
|
||||
LINKAGE PacketTlvType packet_get_type(Packet *packet);
|
||||
LINKAGE TlvMetaType packet_get_tlv_meta(Packet *packet, Tlv *tlv);
|
||||
LINKAGE DWORD packet_get_tlv(Packet *packet, TlvType type, Tlv *tlv);
|
||||
@ -267,7 +271,8 @@ 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 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 );
|
||||
|
||||
#endif
|
||||
|
@ -420,9 +420,8 @@ DWORD request_sys_process_thread_set_regs(Remote *remote, Packet *packet)
|
||||
continue;
|
||||
|
||||
// Validate them
|
||||
if ((packet_is_tlv_null_terminated(packet,
|
||||
&nameTlv) != ERROR_SUCCESS) ||
|
||||
(valueTlv.header.length < sizeof(ULONG)))
|
||||
if ((packet_is_tlv_null_terminated(&nameTlv) != ERROR_SUCCESS)
|
||||
|| (valueTlv.header.length < sizeof(ULONG)))
|
||||
continue;
|
||||
|
||||
// Stash them
|
||||
|
Loading…
x
Reference in New Issue
Block a user