mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-03-18 15:14:10 +01:00
Pivot stability, fixes, tidies, etc
This commit is contained in:
parent
5a04de0780
commit
415665ef59
@ -12,7 +12,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define SAFE_FREE(x) {free(x); x = NULL;}
|
#define SAFE_FREE(x) if(x){free(x);x=NULL;}
|
||||||
|
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -23,19 +23,23 @@ DWORD pivot_tree_add_node(PivotNode* parent, PivotNode* node)
|
|||||||
{
|
{
|
||||||
if (parent->left == NULL)
|
if (parent->left == NULL)
|
||||||
{
|
{
|
||||||
|
dprintf("[PIVOTTREE] Adding node to left");
|
||||||
parent->left = node;
|
parent->left = node;
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dprintf("[PIVOTTREE] Adding node to left subtree");
|
||||||
return pivot_tree_add_node(parent->left, node);
|
return pivot_tree_add_node(parent->left, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent->right == NULL)
|
if (parent->right == NULL)
|
||||||
{
|
{
|
||||||
|
dprintf("[PIVOTTREE] Adding node to right");
|
||||||
parent->right = node;
|
parent->right = node;
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dprintf("[PIVOTTREE] Adding node to right subtree");
|
||||||
return pivot_tree_add_node(parent->right, node);
|
return pivot_tree_add_node(parent->right, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +48,7 @@ DWORD pivot_tree_add(PivotTree* tree, LPBYTE guid, PivotContext* ctx)
|
|||||||
PivotNode* node = (PivotNode*)calloc(1, sizeof(PivotNode));
|
PivotNode* node = (PivotNode*)calloc(1, sizeof(PivotNode));
|
||||||
#ifdef DEBUGTRACE
|
#ifdef DEBUGTRACE
|
||||||
PUCHAR h = (PUCHAR)&guid[0];
|
PUCHAR h = (PUCHAR)&guid[0];
|
||||||
dprintf("[PIVOTTREE] Adding Session GUID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
dprintf("[PIVOTTREE] Adding GUID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
|
h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -74,14 +78,16 @@ PivotNode* pivot_tree_largest_node(PivotNode* node)
|
|||||||
return pivot_tree_largest_node(node->right);
|
return pivot_tree_largest_node(node->right);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD pivot_tree_remove_node(PivotNode* parent, LPBYTE guid)
|
PivotContext* pivot_tree_remove_node(PivotNode* parent, LPBYTE guid)
|
||||||
{
|
{
|
||||||
int cmp = memcmp(parent->guid, guid, sizeof(parent->guid));
|
int cmp = memcmp(parent->guid, guid, sizeof(parent->guid));
|
||||||
if (cmp < 0 && parent->left != NULL)
|
if (cmp < 0 && parent->left != NULL)
|
||||||
{
|
{
|
||||||
|
dprintf("[PIVOTTREE] Removing from left subtree");
|
||||||
int cmp = memcmp(parent->left->guid, guid, sizeof(parent->guid));
|
int cmp = memcmp(parent->left->guid, guid, sizeof(parent->guid));
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
|
dprintf("[PIVOTTREE] Removing right child");
|
||||||
PivotNode* remove = parent->left;
|
PivotNode* remove = parent->left;
|
||||||
PivotNode* left = remove->left;
|
PivotNode* left = remove->left;
|
||||||
PivotNode* largest = pivot_tree_largest_node(left);
|
PivotNode* largest = pivot_tree_largest_node(left);
|
||||||
@ -96,8 +102,9 @@ DWORD pivot_tree_remove_node(PivotNode* parent, LPBYTE guid)
|
|||||||
parent->left = remove->right;
|
parent->left = remove->right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PivotContext* context = remove->ctx;
|
||||||
free(remove);
|
free(remove);
|
||||||
return ERROR_SUCCESS;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pivot_tree_remove_node(parent->left, guid);
|
return pivot_tree_remove_node(parent->left, guid);
|
||||||
@ -105,9 +112,11 @@ DWORD pivot_tree_remove_node(PivotNode* parent, LPBYTE guid)
|
|||||||
|
|
||||||
if (cmp > 0 && parent->right != NULL)
|
if (cmp > 0 && parent->right != NULL)
|
||||||
{
|
{
|
||||||
|
dprintf("[PIVOTTREE] Removing from right subtree");
|
||||||
int cmp = memcmp(parent->right->guid, guid, sizeof(parent->guid));
|
int cmp = memcmp(parent->right->guid, guid, sizeof(parent->guid));
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
|
dprintf("[PIVOTTREE] Removing right child");
|
||||||
PivotNode* remove = parent->right;
|
PivotNode* remove = parent->right;
|
||||||
PivotNode* left = remove->left;
|
PivotNode* left = remove->left;
|
||||||
PivotNode* largest = pivot_tree_largest_node(left);
|
PivotNode* largest = pivot_tree_largest_node(left);
|
||||||
@ -122,27 +131,35 @@ DWORD pivot_tree_remove_node(PivotNode* parent, LPBYTE guid)
|
|||||||
parent->right = remove->right;
|
parent->right = remove->right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PivotContext* context = remove->ctx;
|
||||||
free(remove);
|
free(remove);
|
||||||
return ERROR_SUCCESS;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pivot_tree_remove_node(parent->left, guid);
|
return pivot_tree_remove_node(parent->left, guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD pivot_tree_remove(PivotTree* tree, LPBYTE guid)
|
PivotContext* pivot_tree_remove(PivotTree* tree, LPBYTE guid)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUGTRACE
|
||||||
|
PUCHAR h = (PUCHAR)&guid[0];
|
||||||
|
dprintf("[PIVOTTREE] Removing GUID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
|
h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (tree->head == NULL)
|
if (tree->head == NULL)
|
||||||
{
|
{
|
||||||
return ERROR_SUCCESS;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmp = memcmp(tree->head->guid, guid, sizeof(tree->head->guid));
|
int cmp = memcmp(tree->head->guid, guid, sizeof(tree->head->guid));
|
||||||
|
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
|
dprintf("[PIVOTTREE] Removing head node");
|
||||||
PivotNode* remove = tree->head;
|
PivotNode* remove = tree->head;
|
||||||
PivotNode* left = tree->head->left;
|
PivotNode* left = tree->head->left;
|
||||||
PivotNode* largest = pivot_tree_largest_node(left);
|
PivotNode* largest = pivot_tree_largest_node(left);
|
||||||
@ -157,10 +174,12 @@ DWORD pivot_tree_remove(PivotTree* tree, LPBYTE guid)
|
|||||||
tree->head = tree->head->right;
|
tree->head = tree->head->right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PivotContext* context = remove->ctx;
|
||||||
free(remove);
|
free(remove);
|
||||||
return ERROR_SUCCESS;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dprintf("[PIVOTTREE] Removing non-head node");
|
||||||
return pivot_tree_remove_node(tree->head, guid);
|
return pivot_tree_remove_node(tree->head, guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,24 +193,27 @@ PivotContext* pivot_tree_find_node(PivotNode* node, LPBYTE guid)
|
|||||||
|
|
||||||
#ifdef DEBUGTRACE
|
#ifdef DEBUGTRACE
|
||||||
PUCHAR h = (PUCHAR)&guid[0];
|
PUCHAR h = (PUCHAR)&guid[0];
|
||||||
dprintf("[PIVOTTREE] Session GUID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
dprintf("[PIVOTTREE] Saerch GUID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
|
h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
|
||||||
h = node->guid;
|
h = node->guid;
|
||||||
dprintf("[PIVOTTREE] Node GUID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
dprintf("[PIVOTTREE] Node GUID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
|
h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int cmp = memcmp(guid, node->guid, sizeof(guid));
|
int cmp = memcmp(node->guid, guid, sizeof(node->guid));
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
|
dprintf("[PIVOTTREE] node found");
|
||||||
return node->ctx;
|
return node->ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
{
|
{
|
||||||
|
dprintf("[PIVOTTREE] Searching left subtree");
|
||||||
return pivot_tree_find_node(node->left, guid);
|
return pivot_tree_find_node(node->left, guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dprintf("[PIVOTTREE] Searching right subtree");
|
||||||
return pivot_tree_find_node(node->right, guid);
|
return pivot_tree_find_node(node->right, guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
#define _METERPRETER_PIVOT_TREE
|
#define _METERPRETER_PIVOT_TREE
|
||||||
|
|
||||||
typedef DWORD(*PivotWritePacket)(LPVOID state, LPBYTE rawPacket, DWORD rawPacketLength);
|
typedef DWORD(*PivotWritePacket)(LPVOID state, LPBYTE rawPacket, DWORD rawPacketLength);
|
||||||
|
typedef DWORD(*PivotRemove)(LPVOID state);
|
||||||
|
|
||||||
typedef struct _PivotContext
|
typedef struct _PivotContext
|
||||||
{
|
{
|
||||||
PivotWritePacket packet_write;
|
PivotWritePacket packet_write;
|
||||||
|
PivotRemove remove;
|
||||||
LPVOID state;
|
LPVOID state;
|
||||||
} PivotContext;
|
} PivotContext;
|
||||||
|
|
||||||
@ -20,7 +22,7 @@ typedef void(*PivotTreeTraverseCallback)(LPBYTE guid, PivotContext* ctx, LPVOID
|
|||||||
|
|
||||||
PivotTree* pivot_tree_create();
|
PivotTree* pivot_tree_create();
|
||||||
DWORD pivot_tree_add(PivotTree* tree, LPBYTE guid, PivotContext* ctx);
|
DWORD pivot_tree_add(PivotTree* tree, LPBYTE guid, PivotContext* ctx);
|
||||||
DWORD pivot_tree_remove(PivotTree* tree, LPBYTE guid);
|
PivotContext* pivot_tree_remove(PivotTree* tree, LPBYTE guid);
|
||||||
PivotContext* pivot_tree_find(PivotTree* tree, LPBYTE guid);
|
PivotContext* pivot_tree_find(PivotTree* tree, LPBYTE guid);
|
||||||
void pivot_tree_traverse(PivotTree* tree, PivotTreeTraverseCallback callback, LPVOID state);
|
void pivot_tree_traverse(PivotTree* tree, PivotTreeTraverseCallback callback, LPVOID state);
|
||||||
void pivot_tree_destroy(PivotTree* tree);
|
void pivot_tree_destroy(PivotTree* tree);
|
||||||
|
@ -27,7 +27,8 @@ Remote* remote_allocate()
|
|||||||
|
|
||||||
remote->lock = lock;
|
remote->lock = lock;
|
||||||
remote->enc_ctx = NULL;
|
remote->enc_ctx = NULL;
|
||||||
remote->pivots = pivot_tree_create();
|
remote->pivot_sessions = pivot_tree_create();
|
||||||
|
remote->pivot_listeners = pivot_tree_create();
|
||||||
|
|
||||||
dprintf("[REMOTE] remote created %p", remote);
|
dprintf("[REMOTE] remote created %p", remote);
|
||||||
return remote;
|
return remote;
|
||||||
@ -38,9 +39,14 @@ Remote* remote_allocate()
|
|||||||
lock_destroy(lock);
|
lock_destroy(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remote->pivots)
|
if (remote->pivot_sessions)
|
||||||
{
|
{
|
||||||
pivot_tree_destroy(remote->pivots);
|
pivot_tree_destroy(remote->pivot_sessions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote->pivot_listeners)
|
||||||
|
{
|
||||||
|
pivot_tree_destroy(remote->pivot_listeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remote)
|
if (remote)
|
||||||
@ -59,7 +65,8 @@ Remote* remote_allocate()
|
|||||||
VOID remote_deallocate(Remote * remote)
|
VOID remote_deallocate(Remote * remote)
|
||||||
{
|
{
|
||||||
free_encryption_context(remote);
|
free_encryption_context(remote);
|
||||||
pivot_tree_destroy(remote->pivots);
|
pivot_tree_destroy(remote->pivot_sessions);
|
||||||
|
pivot_tree_destroy(remote->pivot_listeners);
|
||||||
|
|
||||||
if (remote->lock)
|
if (remote->lock)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +160,8 @@ typedef struct _Remote
|
|||||||
int sess_expiry_end; ///! Unix timestamp for when the server should shut down.
|
int sess_expiry_end; ///! Unix timestamp for when the server should shut down.
|
||||||
int sess_start_time; ///! Unix timestamp representing the session startup time.
|
int sess_start_time; ///! Unix timestamp representing the session startup time.
|
||||||
|
|
||||||
PivotTree* pivots; ///! Collection of active Meterpreter session pivots.
|
PivotTree* pivot_sessions; ///! Collection of active Meterpreter session pivots.
|
||||||
|
PivotTree* pivot_listeners; ///! Collection of active Meterpreter pivot listeners.
|
||||||
|
|
||||||
PacketEncryptionContext* enc_ctx; ///! Reference to the packet encryption context.
|
PacketEncryptionContext* enc_ctx; ///! Reference to the packet encryption context.
|
||||||
} Remote;
|
} Remote;
|
||||||
|
@ -23,6 +23,7 @@ Command customCommands[] =
|
|||||||
COMMAND_REQ("core_set_session_guid", request_core_set_session_guid),
|
COMMAND_REQ("core_set_session_guid", request_core_set_session_guid),
|
||||||
COMMAND_REQ("core_set_uuid", request_core_set_uuid),
|
COMMAND_REQ("core_set_uuid", request_core_set_uuid),
|
||||||
COMMAND_REQ("core_pivot_add", request_core_pivot_add),
|
COMMAND_REQ("core_pivot_add", request_core_pivot_add),
|
||||||
|
COMMAND_REQ("core_pivot_remove", request_core_pivot_remove),
|
||||||
COMMAND_INLINE_REP("core_patch_url", request_core_patch_url),
|
COMMAND_INLINE_REP("core_patch_url", request_core_patch_url),
|
||||||
COMMAND_TERMINATOR
|
COMMAND_TERMINATOR
|
||||||
};
|
};
|
||||||
|
@ -15,4 +15,31 @@ DWORD request_core_pivot_add(Remote* remote, Packet* packet)
|
|||||||
{
|
{
|
||||||
// Right now we only support named pipe pivotes, so just go straight there
|
// Right now we only support named pipe pivotes, so just go straight there
|
||||||
return request_core_pivot_add_named_pipe(remote, packet);
|
return request_core_pivot_add_named_pipe(remote, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Remove a pivot point from the current Meterpreter instance.
|
||||||
|
* @remote Pointer to the \c Remote instance.
|
||||||
|
* @remote Pointer to the incoming request \c Packet instance.
|
||||||
|
* @return Indication of error or success.
|
||||||
|
*/
|
||||||
|
DWORD request_core_pivot_remove(Remote* remote, Packet* packet)
|
||||||
|
{
|
||||||
|
DWORD result = ERROR_NOT_FOUND;
|
||||||
|
LPBYTE pivotId = packet_get_tlv_value_raw(packet, TLV_TYPE_PIVOT_ID);
|
||||||
|
|
||||||
|
if (pivotId != NULL)
|
||||||
|
{
|
||||||
|
PivotContext* ctx = pivot_tree_remove(remote->pivot_listeners, pivotId);
|
||||||
|
if (ctx != NULL)
|
||||||
|
{
|
||||||
|
ctx->remove(ctx->state);
|
||||||
|
free(ctx);
|
||||||
|
result = ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
packet_transmit_empty_response(remote, packet, result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef _METERPRETER_SERVER_PIVOT
|
#ifndef _METERPRETER_SERVER_PIVOT
|
||||||
#define _METERPRETER_SERVER_PIVOT
|
#define _METERPRETER_SERVER_PIVOT
|
||||||
|
|
||||||
DWORD request_core_pivot_add(Remote* remote, Packet* packet);
|
DWORD request_core_pivot_add(Remote* remote, Packet* packet);
|
||||||
|
DWORD request_core_pivot_remove(Remote* remote, Packet* packet);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -16,6 +16,7 @@ typedef struct _NamedPipeContext
|
|||||||
OVERLAPPED write_overlap;
|
OVERLAPPED write_overlap;
|
||||||
char name[PIPE_NAME_SIZE];
|
char name[PIPE_NAME_SIZE];
|
||||||
GUID pivot_id;
|
GUID pivot_id;
|
||||||
|
GUID pivot_session_guid;
|
||||||
Remote* remote;
|
Remote* remote;
|
||||||
HANDLE pipe;
|
HANDLE pipe;
|
||||||
BOOL connecting;
|
BOOL connecting;
|
||||||
@ -30,6 +31,7 @@ typedef struct _NamedPipeContext
|
|||||||
} NamedPipeContext;
|
} NamedPipeContext;
|
||||||
|
|
||||||
static DWORD server_notify(Remote* remote, LPVOID entryContext, LPVOID threadContext);
|
static DWORD server_notify(Remote* remote, LPVOID entryContext, LPVOID threadContext);
|
||||||
|
static DWORD server_destroy(HANDLE waitable, LPVOID entryContext, LPVOID threadContext);
|
||||||
|
|
||||||
typedef BOOL (WINAPI *PAddMandatoryAce)(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags, DWORD dwMandatoryPolicy, PSID pLabelSid);
|
typedef BOOL (WINAPI *PAddMandatoryAce)(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags, DWORD dwMandatoryPolicy, PSID pLabelSid);
|
||||||
static BOOL WINAPI AddMandatoryAce(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags, DWORD dwMandatoryPolicy, PSID pLabelSid)
|
static BOOL WINAPI AddMandatoryAce(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags, DWORD dwMandatoryPolicy, PSID pLabelSid)
|
||||||
@ -57,6 +59,38 @@ static BOOL WINAPI AddMandatoryAce(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFl
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD server_destroy(HANDLE waitable, LPVOID entryContext, LPVOID threadContext)
|
||||||
|
{
|
||||||
|
NamedPipeContext* ctx = (NamedPipeContext*)entryContext;
|
||||||
|
if (ctx != NULL)
|
||||||
|
{
|
||||||
|
dprintf("[PIVOT] Cleaning up the pipe pivot context");
|
||||||
|
lock_acquire(ctx->remote->lock);
|
||||||
|
CloseHandle(ctx->pipe);
|
||||||
|
CloseHandle(ctx->read_overlap.hEvent);
|
||||||
|
CloseHandle(ctx->write_overlap.hEvent);
|
||||||
|
SAFE_FREE(ctx->stage_data);
|
||||||
|
lock_release(ctx->remote->lock);
|
||||||
|
dprintf("[PIVOT] Cleaned up the pipe pivot context");
|
||||||
|
}
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void terminate_pipe(NamedPipeContext* ctx)
|
||||||
|
{
|
||||||
|
if (ctx != NULL)
|
||||||
|
{
|
||||||
|
scheduler_signal_waitable(ctx->read_overlap.hEvent, Stop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD remove_listener(LPVOID state)
|
||||||
|
{
|
||||||
|
dprintf("[PIVOT] removing named pipe listener");
|
||||||
|
terminate_pipe((NamedPipeContext*)state);
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static DWORD read_pipe_to_packet(NamedPipeContext* ctx, LPBYTE source, DWORD sourceSize)
|
static DWORD read_pipe_to_packet(NamedPipeContext* ctx, LPBYTE source, DWORD sourceSize)
|
||||||
{
|
{
|
||||||
// Make sure we have the space to handle the incoming packet
|
// Make sure we have the space to handle the incoming packet
|
||||||
@ -315,7 +349,8 @@ DWORD create_pipe_server_instance(NamedPipeContext* ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dprintf("[NP-SERVER] Inserting the named pipe schedule entry");
|
dprintf("[NP-SERVER] Inserting the named pipe schedule entry");
|
||||||
scheduler_insert_waitable(ctx->read_overlap.hEvent, ctx, NULL, server_notify, NULL);
|
scheduler_insert_waitable(ctx->read_overlap.hEvent, ctx, NULL, server_notify, server_destroy);
|
||||||
|
//scheduler_insert_waitable(ctx->read_overlap.hEvent, ctx, NULL, server_notify, NULL);
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
return dwResult;
|
return dwResult;
|
||||||
@ -429,8 +464,23 @@ static DWORD server_notify(Remote* remote, LPVOID entryContext, LPVOID threadCon
|
|||||||
else if (dwResult == ERROR_BROKEN_PIPE)
|
else if (dwResult == ERROR_BROKEN_PIPE)
|
||||||
{
|
{
|
||||||
dprintf("[NP-SERVER] the client appears to have bailed out, disconnecting...");
|
dprintf("[NP-SERVER] the client appears to have bailed out, disconnecting...");
|
||||||
|
// Reset the read event so that our schedular loop witll exit properly
|
||||||
ResetEvent(serverCtx->read_overlap.hEvent);
|
ResetEvent(serverCtx->read_overlap.hEvent);
|
||||||
// TODO: do some clean up of stuf here.
|
|
||||||
|
// Prepare the notification packet for dispatching
|
||||||
|
Packet* notification = packet_create(PACKET_TLV_TYPE_REQUEST, "core_pivot_session_died");
|
||||||
|
packet_add_tlv_raw(notification, TLV_TYPE_SESSION_GUID, (LPVOID)&serverCtx->pivot_session_guid, sizeof(serverCtx->pivot_session_guid));
|
||||||
|
|
||||||
|
// Clean up the pivot context
|
||||||
|
PivotContext* pivotCtx = pivot_tree_remove(remote->pivot_sessions, (LPBYTE)&serverCtx->pivot_session_guid);
|
||||||
|
SAFE_FREE(pivotCtx);
|
||||||
|
|
||||||
|
// Clean up all the named pipe context stuff.
|
||||||
|
terminate_pipe(serverCtx);
|
||||||
|
|
||||||
|
// Inform MSF of the dead session
|
||||||
|
packet_transmit(serverCtx->remote, notification, NULL);
|
||||||
|
|
||||||
return ERROR_BROKEN_PIPE;
|
return ERROR_BROKEN_PIPE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -454,6 +504,7 @@ static DWORD server_notify(Remote* remote, LPVOID entryContext, LPVOID threadCon
|
|||||||
nextCtx->remote = serverCtx->remote;
|
nextCtx->remote = serverCtx->remote;
|
||||||
nextCtx->stage_data = serverCtx->stage_data;
|
nextCtx->stage_data = serverCtx->stage_data;
|
||||||
nextCtx->stage_data_size = serverCtx->stage_data_size;
|
nextCtx->stage_data_size = serverCtx->stage_data_size;
|
||||||
|
memcpy_s(&nextCtx->pivot_id, sizeof(nextCtx->pivot_id), &serverCtx->pivot_id, sizeof(nextCtx->pivot_id));
|
||||||
memcpy_s(&nextCtx->name, PIPE_NAME_SIZE, &serverCtx->name, PIPE_NAME_SIZE);
|
memcpy_s(&nextCtx->name, PIPE_NAME_SIZE, &serverCtx->name, PIPE_NAME_SIZE);
|
||||||
|
|
||||||
// create a new pipe for the next connection
|
// create a new pipe for the next connection
|
||||||
@ -466,6 +517,16 @@ static DWORD server_notify(Remote* remote, LPVOID entryContext, LPVOID threadCon
|
|||||||
|
|
||||||
serverCtx->established = TRUE;
|
serverCtx->established = TRUE;
|
||||||
|
|
||||||
|
// The current listener cotnext in the listeners tree points to the server instance that has now
|
||||||
|
// become a client instance due to the new connection. Therefore we need to update the pivot tree context
|
||||||
|
// to point to the new listener on the named pipe.
|
||||||
|
PivotContext* listenerCtx = pivot_tree_find(remote->pivot_listeners, (LPBYTE)&serverCtx->pivot_id);
|
||||||
|
if (listenerCtx != NULL)
|
||||||
|
{
|
||||||
|
dprintf("[NP-SERVER] Updating the listener context in the pivot tree");
|
||||||
|
listenerCtx->state = nextCtx;
|
||||||
|
}
|
||||||
|
|
||||||
// Time to stage the data
|
// Time to stage the data
|
||||||
if (serverCtx->stage_data && serverCtx->stage_data_size > 0)
|
if (serverCtx->stage_data && serverCtx->stage_data_size > 0)
|
||||||
{
|
{
|
||||||
@ -475,25 +536,29 @@ static DWORD server_notify(Remote* remote, LPVOID entryContext, LPVOID threadCon
|
|||||||
|
|
||||||
// send the stage
|
// send the stage
|
||||||
named_pipe_write_raw(serverCtx, serverCtx->stage_data, serverCtx->stage_data_size);
|
named_pipe_write_raw(serverCtx, serverCtx->stage_data, serverCtx->stage_data_size);
|
||||||
|
|
||||||
|
// to "hand over" the stage data, set the existing pointer to NULL so that things don't get freed
|
||||||
|
// when they shouldn't be.
|
||||||
|
serverCtx->stage_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to generate a new session GUID and inform metasploit of the new session
|
// We need to generate a new session GUID and inform metasploit of the new session
|
||||||
GUID guid;
|
CoCreateGuid(&serverCtx->pivot_session_guid);
|
||||||
CoCreateGuid(&guid);
|
|
||||||
// swizzle the values around so that endianness isn't an issue before casting to a block of bytes
|
// swizzle the values around so that endianness isn't an issue before casting to a block of bytes
|
||||||
guid.Data1 = htonl(guid.Data1);
|
serverCtx->pivot_session_guid.Data1 = htonl(serverCtx->pivot_session_guid.Data1);
|
||||||
guid.Data2 = htons(guid.Data2);
|
serverCtx->pivot_session_guid.Data2 = htons(serverCtx->pivot_session_guid.Data2);
|
||||||
guid.Data3 = htons(guid.Data3);
|
serverCtx->pivot_session_guid.Data3 = htons(serverCtx->pivot_session_guid.Data3);
|
||||||
|
|
||||||
Packet* notification = packet_create(PACKET_TLV_TYPE_REQUEST, "core_pivot_session_new");
|
Packet* notification = packet_create(PACKET_TLV_TYPE_REQUEST, "core_pivot_session_new");
|
||||||
packet_add_tlv_raw(notification, TLV_TYPE_SESSION_GUID, (LPVOID)&guid, sizeof(guid));
|
packet_add_tlv_raw(notification, TLV_TYPE_SESSION_GUID, (LPVOID)&serverCtx->pivot_session_guid, sizeof(serverCtx->pivot_session_guid));
|
||||||
packet_add_tlv_raw(notification, TLV_TYPE_PIVOT_ID, (LPVOID)&serverCtx->pivot_id, sizeof(serverCtx->pivot_id));
|
packet_add_tlv_raw(notification, TLV_TYPE_PIVOT_ID, (LPVOID)&serverCtx->pivot_id, sizeof(serverCtx->pivot_id));
|
||||||
packet_transmit(serverCtx->remote, notification, NULL);
|
packet_transmit(serverCtx->remote, notification, NULL);
|
||||||
|
|
||||||
PivotContext* pivotContext = (PivotContext*)calloc(1, sizeof(PivotContext));
|
PivotContext* pivotContext = (PivotContext*)calloc(1, sizeof(PivotContext));
|
||||||
pivotContext->state = serverCtx;
|
pivotContext->state = serverCtx;
|
||||||
pivotContext->packet_write = named_pipe_write_raw;
|
pivotContext->packet_write = named_pipe_write_raw;
|
||||||
pivot_tree_add(serverCtx->remote->pivots, (LPBYTE)&guid, pivotContext);
|
pivot_tree_add(remote->pivot_sessions, (LPBYTE)&serverCtx->pivot_session_guid, pivotContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytesProcessed > 0)
|
if (bytesProcessed > 0)
|
||||||
@ -602,6 +667,10 @@ DWORD request_core_pivot_add_named_pipe(Remote* remote, Packet* packet)
|
|||||||
if (dwResult == ERROR_SUCCESS)
|
if (dwResult == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
dprintf("[NP-SERVER] request_net_named_pipe_server_channel_open. named pipe server %s", namedPipeName);
|
dprintf("[NP-SERVER] request_net_named_pipe_server_channel_open. named pipe server %s", namedPipeName);
|
||||||
|
PivotContext* pivotCtx = (PivotContext*)calloc(1, sizeof(PivotContext));
|
||||||
|
pivotCtx->state = ctx;
|
||||||
|
pivotCtx->remove = remove_listener;
|
||||||
|
pivot_tree_add(remote->pivot_listeners, pivotId, pivotCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (0);
|
} while (0);
|
||||||
|
@ -32,7 +32,7 @@ static DWORD server_pipe_poll(Remote* remote, long timeout)
|
|||||||
|
|
||||||
lock_acquire(remote->lock);
|
lock_acquire(remote->lock);
|
||||||
|
|
||||||
dprintf("[NP DISPATCH] testing for data on the pipe, making sure there's enough for a packet header");
|
vdprintf("[NP DISPATCH] testing for data on the pipe, making sure there's enough for a packet header");
|
||||||
BOOL ready = PeekNamedPipe(ctx->pipe, NULL, 0, NULL, &bytesAvailable, NULL) && bytesAvailable >= sizeof(PacketHeader);
|
BOOL ready = PeekNamedPipe(ctx->pipe, NULL, 0, NULL, &bytesAvailable, NULL) && bytesAvailable >= sizeof(PacketHeader);
|
||||||
DWORD result = GetLastError();
|
DWORD result = GetLastError();
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ static DWORD server_pipe_poll(Remote* remote, long timeout)
|
|||||||
|
|
||||||
if (ready)
|
if (ready)
|
||||||
{
|
{
|
||||||
dprintf("[NP DISPATCH] pipe data found %u bytes", bytesAvailable);
|
vdprintf("[NP DISPATCH] pipe data found %u bytes", bytesAvailable);
|
||||||
result = ERROR_SUCCESS;
|
result = ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -48,7 +48,7 @@ static DWORD server_pipe_poll(Remote* remote, long timeout)
|
|||||||
if (result != ERROR_BROKEN_PIPE)
|
if (result != ERROR_BROKEN_PIPE)
|
||||||
{
|
{
|
||||||
// simulate a wait so that we don't bash the crap out of the CPU?
|
// simulate a wait so that we don't bash the crap out of the CPU?
|
||||||
dprintf("[NP DISPATCH] pipe data not found, sleeping (error %u)", GetLastError());
|
vdprintf("[NP DISPATCH] pipe data not found, sleeping (error %u)", GetLastError());
|
||||||
Sleep(timeout);
|
Sleep(timeout);
|
||||||
result = ERROR_NO_DATA;
|
result = ERROR_NO_DATA;
|
||||||
}
|
}
|
||||||
@ -175,9 +175,9 @@ static DWORD packet_receive_named_pipe(Remote *remote, Packet **packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
payloadLength = ntohl(header.length) - sizeof(TlvHeader);
|
payloadLength = ntohl(header.length) - sizeof(TlvHeader);
|
||||||
vdprintf("[PIPE] Payload length is %d", payloadLength);
|
dprintf("[PIPE] Payload length is %d", payloadLength);
|
||||||
DWORD packetSize = sizeof(PacketHeader) + payloadLength;
|
DWORD packetSize = sizeof(PacketHeader) + payloadLength;
|
||||||
vdprintf("[PIPE] total buffer size for the packet is %d", packetSize);
|
dprintf("[PIPE] total buffer size for the packet is %d", packetSize);
|
||||||
payloadBytesLeft = payloadLength;
|
payloadBytesLeft = payloadLength;
|
||||||
|
|
||||||
// Allocate the payload
|
// Allocate the payload
|
||||||
@ -199,6 +199,7 @@ static DWORD packet_receive_named_pipe(Remote *remote, Packet **packet)
|
|||||||
|
|
||||||
// Read the payload
|
// Read the payload
|
||||||
DWORD bytesAvailable = 0;
|
DWORD bytesAvailable = 0;
|
||||||
|
dprintf("[PIPE] Beginning read loop for a total of %u", payloadBytesLeft);
|
||||||
while (payloadBytesLeft > 0)
|
while (payloadBytesLeft > 0)
|
||||||
{
|
{
|
||||||
dprintf("[PIPE] Trying to read %u (0x%x) bytes", payloadBytesLeft, payloadBytesLeft);
|
dprintf("[PIPE] Trying to read %u (0x%x) bytes", payloadBytesLeft, payloadBytesLeft);
|
||||||
|
@ -475,7 +475,7 @@ static DWORD packet_receive(Remote *remote, Packet **packet)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
dprintf("[TCP] Session GUIDs don't match, looking for a pivot");
|
dprintf("[TCP] Session GUIDs don't match, looking for a pivot");
|
||||||
PivotContext* pivotCtx = pivot_tree_find(remote->pivots, header.session_guid);
|
PivotContext* pivotCtx = pivot_tree_find(remote->pivot_sessions, header.session_guid);
|
||||||
if (pivotCtx != NULL)
|
if (pivotCtx != NULL)
|
||||||
{
|
{
|
||||||
dprintf("[TCP] Pivot found, dispatching packet");
|
dprintf("[TCP] Pivot found, dispatching packet");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user