mirror of
https://github.com/rapid7/metasploit-payloads
synced 2024-12-08 23:33:07 +01:00
Refactor XOR code, dedup packet writing code
This commit is contained in:
parent
f5690866f8
commit
7e8b4c3c52
@ -108,7 +108,7 @@ void enable_debugging()
|
||||
|
||||
#endif
|
||||
|
||||
VOID xor_bytes(DWORD xorKey, LPBYTE buffer, DWORD bufferSize)
|
||||
VOID xor_bytes(BYTE xorKey[sizeof(DWORD)], LPBYTE buffer, DWORD bufferSize)
|
||||
{
|
||||
static BOOL initialised = FALSE;
|
||||
if (!initialised)
|
||||
@ -117,10 +117,8 @@ VOID xor_bytes(DWORD xorKey, LPBYTE buffer, DWORD bufferSize)
|
||||
initialised = TRUE;
|
||||
}
|
||||
|
||||
LPBYTE xor = (LPBYTE)&xorKey;
|
||||
|
||||
for (DWORD i = 0; i < bufferSize; ++i)
|
||||
{
|
||||
buffer[i] ^= xor[i % sizeof(DWORD)];
|
||||
buffer[i] ^= xorKey[i % sizeof(DWORD)];
|
||||
}
|
||||
}
|
||||
|
@ -233,4 +233,4 @@ static _inline void real_dprintf(char *format, ...)
|
||||
#endif
|
||||
|
||||
int current_unix_timestamp(void);
|
||||
VOID xor_bytes(DWORD xorKey, LPBYTE buffer, DWORD bufferSize);
|
||||
VOID xor_bytes(BYTE xorKey[sizeof(DWORD)], LPBYTE buffer, DWORD bufferSize);
|
@ -140,6 +140,100 @@ VOID core_update_desktop(Remote * remote, DWORD dwSessionID, char * cpStationNam
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Serialize a packet to a byte stream, and destroy the packet.
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @param packet Pointer to the packet to serialize.
|
||||
* @param buffer Pointer that will receive a pointer to the serialized packet buffer.
|
||||
* @param bufferSize Pointer that will receive the resulting serialized packet buffer size.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD packet_serialize_and_destroy(Remote* remote, Packet* packet, BYTE** buffer, size_t* bufferSize)
|
||||
{
|
||||
CryptoContext* crypto;
|
||||
Tlv requestId;
|
||||
DWORD res = ERROR_SUCCESS;
|
||||
|
||||
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 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));
|
||||
}
|
||||
|
||||
// create a buffer for the serialized packet
|
||||
*bufferSize = sizeof(packet->header) + packet->payloadLength;
|
||||
*buffer = (BYTE*)calloc(1, *bufferSize);
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
res = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
// generate a new XOR key
|
||||
DWORD xorKey = rand_xor_key();
|
||||
|
||||
// make sure the existing XOR key it set to zero, we'll be overwriting
|
||||
// it shortly
|
||||
memset(packet->header.xor_key, 0, sizeof(packet->header.xor_key));
|
||||
|
||||
// copy the header & payload over to the buffer
|
||||
memcpy(*buffer, &packet->header, sizeof(packet->header));
|
||||
memcpy(*buffer + sizeof(packet->header), packet->payload, packet->payloadLength);
|
||||
|
||||
// XOR the entire buffer, with they key (results in the xor key being written
|
||||
// to the first 4 bytes because they're currently zero anyway
|
||||
xor_bytes((BYTE*)&xorKey, *buffer, (DWORD)*bufferSize);
|
||||
} while (0);
|
||||
|
||||
// Destroy the packet
|
||||
packet_destroy(packet);
|
||||
|
||||
lock_release(remote->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Create a packet of a given type (request/response) and method.
|
||||
* @param type The TLV type that this packet represents.
|
||||
|
@ -196,7 +196,7 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD xor_key;
|
||||
BYTE xor_key[sizeof(DWORD)];
|
||||
DWORD length;
|
||||
DWORD type;
|
||||
} PacketHeader;
|
||||
@ -237,6 +237,7 @@ typedef struct _PacketRequestCompletion
|
||||
/*
|
||||
* Packet manipulation
|
||||
*/
|
||||
LINKAGE DWORD packet_serialize_and_destroy(Remote* remote, Packet* packet, BYTE** buffer, size_t* bufferSize);
|
||||
LINKAGE Packet *packet_create(PacketTlvType type, LPCSTR method);
|
||||
LINKAGE Packet *packet_create_response(Packet *packet);
|
||||
LINKAGE Packet* packet_create_group();
|
||||
|
@ -529,133 +529,61 @@ out:
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
dprintf("[PACKET] New xor key for sending");
|
||||
packet->header.xor_key = rand_xor_key();
|
||||
// before transmission, xor the whole lot, starting with the body
|
||||
xor_bytes(packet->header.xor_key, (LPBYTE)packet->payload, packet->payloadLength);
|
||||
// then the header
|
||||
xor_bytes(packet->header.xor_key, (LPBYTE)&packet->header.length, 8);
|
||||
// be sure to switch the xor header before writing
|
||||
packet->header.xor_key = htonl(packet->header.xor_key);
|
||||
|
||||
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);
|
||||
|
||||
BYTE* buffer = NULL;
|
||||
size_t bufferSize = 0;
|
||||
Tlv requestId;
|
||||
TcpTransportContext* ctx = (TcpTransportContext*)remote->transport->ctx;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
dprintf("[TRANSMIT] Serializing the packet");
|
||||
DWORD res = packet_serialize_and_destroy(remote, packet, &buffer, &bufferSize);
|
||||
dprintf("[TRANSMIT] Packet serialised with result: %d 0x%x, buffer: %p, size: %u", res, res, buffer, bufferSize);
|
||||
|
||||
lock_acquire(remote->lock);
|
||||
|
||||
do
|
||||
{
|
||||
if (res != ERROR_SUCCESS || buffer == NULL)
|
||||
{
|
||||
dprintf("[PACKET] Error during serialization");
|
||||
break;
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
int written = 0;
|
||||
vdprintf("[TRANSMIT] sent %u of %u", index, bufferSize);
|
||||
while (index < bufferSize)
|
||||
{
|
||||
// Transmit the packet's header (length, type)
|
||||
written = SSL_write(ctx->ssl, buffer + index, (int)(bufferSize - index));
|
||||
|
||||
if (written <= 0)
|
||||
{
|
||||
dprintf("[PACKET] transmit header failed with return %d at index %d\n", written, index);
|
||||
res = GetLastError();
|
||||
break;
|
||||
}
|
||||
index += written;
|
||||
vdprintf("[TRANSMIT] sent %u of %u", index, bufferSize);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
lock_release(remote->lock);
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
dprintf("[TRANSMIT] result of packet sending: %d 0x%x", res, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -715,10 +643,8 @@ static DWORD packet_receive_via_ssl(Remote *remote, Packet **packet)
|
||||
break;
|
||||
}
|
||||
|
||||
header.xor_key = ntohl(header.xor_key);
|
||||
|
||||
// xor the header data
|
||||
xor_bytes(header.xor_key, &header.length, 8);
|
||||
xor_bytes(header.xor_key, (PUCHAR)&header.length, 8);
|
||||
|
||||
// Initialize the header
|
||||
header.length = ntohl(header.length);
|
||||
|
@ -617,8 +617,6 @@ static DWORD packet_receive_via_ssl(Remote *remote, Packet **packet)
|
||||
break;
|
||||
}
|
||||
|
||||
header.xor_key = ntohl(header.xor_key);
|
||||
|
||||
// xor the header data
|
||||
xor_bytes(header.xor_key, (LPBYTE)&header.length, 8);
|
||||
|
||||
@ -1004,135 +1002,61 @@ static BOOL configure_tcp_connection(Transport* transport)
|
||||
*/
|
||||
DWORD packet_transmit_via_ssl(Remote* remote, Packet* packet, PacketRequestCompletion* completion)
|
||||
{
|
||||
CryptoContext* crypto;
|
||||
BYTE* buffer = NULL;
|
||||
size_t bufferSize = 0;
|
||||
Tlv requestId;
|
||||
DWORD res;
|
||||
DWORD idx;
|
||||
TcpTransportContext* ctx = (TcpTransportContext*)remote->transport->ctx;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
dprintf("[TRANSMIT] Sending packet to the server");
|
||||
|
||||
dprintf("[TRANSMIT] Serializing the packet");
|
||||
DWORD res = packet_serialize_and_destroy(remote, packet, &buffer, &bufferSize);
|
||||
dprintf("[TRANSMIT] Packet serialised with result: %d 0x%x, buffer: %p, size: %u", res, res, buffer, bufferSize);
|
||||
|
||||
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))
|
||||
if (res != ERROR_SUCCESS || buffer == NULL)
|
||||
{
|
||||
packet_add_completion_handler((LPCSTR)requestId.buffer, completion);
|
||||
dprintf("[PACKET] Error during serialization");
|
||||
break;
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
size_t index = 0;
|
||||
int written = 0;
|
||||
vdprintf("[TRANSMIT] sent %u of %u", index, bufferSize);
|
||||
while (index < bufferSize)
|
||||
{
|
||||
// Transmit the packet's header (length, type)
|
||||
written = SSL_write(ctx->ssl, buffer + index, (int)(bufferSize - index));
|
||||
|
||||
dprintf("[PACKET] New xor key for sending");
|
||||
packet->header.xor_key = rand_xor_key();
|
||||
// before transmission, xor the whole lot, starting with the body
|
||||
xor_bytes(packet->header.xor_key, (LPBYTE)packet->payload, packet->payloadLength);
|
||||
// then the header
|
||||
xor_bytes(packet->header.xor_key, (LPBYTE)&packet->header.length, 8);
|
||||
// be sure to switch the xor header before writing
|
||||
packet->header.xor_key = htonl(packet->header.xor_key);
|
||||
|
||||
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 (written <= 0)
|
||||
{
|
||||
dprintf("[PACKET] transmit header failed with return %d at index %d\n", written, index);
|
||||
res = GetLastError();
|
||||
break;
|
||||
}
|
||||
index += written;
|
||||
vdprintf("[TRANSMIT] sent %u of %u", index, bufferSize);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
dprintf("[TRANSMIT] result of packet sending: %d 0x%x", res, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -262,60 +262,6 @@ static DWORD validate_response_winhttp(HANDLE hReq, HttpTransportContext* ctx)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @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_http(Remote *remote, Packet *packet, PacketRequestCompletion *completion)
|
||||
{
|
||||
DWORD res = 0;
|
||||
HINTERNET hReq;
|
||||
BOOL result;
|
||||
DWORD retries = 5;
|
||||
HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx;
|
||||
unsigned char *buffer;
|
||||
|
||||
DWORD totalLength = packet->payloadLength + sizeof(PacketHeader);
|
||||
|
||||
buffer = malloc(totalLength);
|
||||
if (!buffer)
|
||||
{
|
||||
SetLastError(ERROR_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buffer, &packet->header, sizeof(PacketHeader));
|
||||
memcpy(buffer + sizeof(PacketHeader), packet->payload, packet->payloadLength);
|
||||
|
||||
do
|
||||
{
|
||||
hReq = ctx->create_req(ctx, FALSE, "PACKET TRANSMIT");
|
||||
if (hReq == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = ctx->send_req(hReq, buffer, totalLength);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
dprintf("[PACKET TRANSMIT] Failed HttpSendRequest: %d", GetLastError());
|
||||
SetLastError(ERROR_NOT_FOUND);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PACKET TRANSMIT] request sent.. apparently");
|
||||
} while(0);
|
||||
|
||||
memset(buffer, 0, totalLength);
|
||||
ctx->close_req(hReq);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Transmit a packet via HTTP(s) _and_ destroy it.
|
||||
* @param remote Pointer to the \c Remote instance.
|
||||
@ -325,94 +271,60 @@ static DWORD packet_transmit_http(Remote *remote, Packet *packet, PacketRequestC
|
||||
*/
|
||||
static DWORD packet_transmit_via_http(Remote *remote, Packet *packet, PacketRequestCompletion *completion)
|
||||
{
|
||||
CryptoContext *crypto;
|
||||
Tlv requestId;
|
||||
DWORD res;
|
||||
DWORD res;
|
||||
BYTE* buffer = NULL;
|
||||
size_t bufferSize = 0;
|
||||
Tlv requestId;
|
||||
HINTERNET hReq = NULL;
|
||||
HttpTransportContext* ctx = (HttpTransportContext*)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));
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
dprintf("[PACKET] New xor key for sending");
|
||||
packet->header.xor_key = rand_xor_key();
|
||||
dprintf("[PACKET] XOR Encoding payload");
|
||||
// before transmission, xor the whole lot, starting with the body
|
||||
xor_bytes(packet->header.xor_key, (LPBYTE)packet->payload, packet->payloadLength);
|
||||
dprintf("[PACKET] XOR Encoding header");
|
||||
// then the header
|
||||
xor_bytes(packet->header.xor_key, (LPBYTE)&packet->header.length, 8);
|
||||
// be sure to switch the xor header before writing
|
||||
packet->header.xor_key = htonl(packet->header.xor_key);
|
||||
|
||||
dprintf("[PACKET] Transmitting packet of length %d to remote", packet->payloadLength);
|
||||
res = packet_transmit_http(remote, packet, completion);
|
||||
if (res < 0)
|
||||
{
|
||||
dprintf("[PACKET] transmit failed with return %d\n", res);
|
||||
break;
|
||||
}
|
||||
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
dprintf("[TRANSMIT] Serializing the packet");
|
||||
res = packet_serialize_and_destroy(remote, packet, &buffer, &bufferSize);
|
||||
|
||||
lock_acquire(remote->lock);
|
||||
|
||||
do
|
||||
{
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
hReq = ctx->create_req(ctx, FALSE, "PACKET TRANSMIT");
|
||||
if (hReq == NULL)
|
||||
{
|
||||
res = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ctx->send_req(hReq, buffer, (DWORD)bufferSize))
|
||||
{
|
||||
res = GetLastError();
|
||||
dprintf("[PACKET TRANSMIT] Failed HttpSendRequest: %d", res);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintf("[PACKET TRANSMIT] request sent.. apparently");
|
||||
} while (0);
|
||||
|
||||
res = GetLastError();
|
||||
|
||||
// Destroy the packet
|
||||
packet_destroy(packet);
|
||||
ctx->close_req(hReq);
|
||||
|
||||
lock_release(remote->lock);
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -522,7 +434,6 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet)
|
||||
}
|
||||
|
||||
dprintf("[PACKET RECEIVE HTTP] decoding header");
|
||||
header.xor_key = ntohl(header.xor_key);
|
||||
xor_bytes(header.xor_key, (LPBYTE)&header.length, 8);
|
||||
header.length = ntohl(header.length);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user