mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-03-18 15:14:10 +01:00

The 'common' library has been removed. The only project that actually used it was metsrv, so the code that metsrv required from common is now directly compiled in as part of that project. The common folder now contains files that are importanta cross all of the projects, with a primary focus on the new "API" style function. What this means is that MetSrv has an API that it exposes through a function pointer that is passed to the extension when it's initialised. This pointer references a structure with all the API functions wired in. This means that: * Extensions don't need to know anything about metsrv at compile time. * The delay loading code can be removed, which was one of the last instances of "metsrv.dll" as a string. * Metsrv.dll no longer exports any functions. More to come.
296 lines
7.2 KiB
C
296 lines
7.2 KiB
C
#include "common.h"
|
|
#include "pivot_tree.h"
|
|
|
|
typedef struct _PivotNode
|
|
{
|
|
BYTE guid[sizeof(GUID)];
|
|
PivotContext* ctx;
|
|
|
|
struct _PivotNode* left;
|
|
struct _PivotNode* right;
|
|
} PivotNode;
|
|
|
|
#ifdef DEBUGTRACE
|
|
void pivot_tree_to_string(char** buffer, PivotNode* node, char* prefix)
|
|
{
|
|
// each line is the prefix size, plus the guid size plus a null and a \n and the two pointers
|
|
int curLen = *buffer ? (int)strlen(*buffer) : 0;
|
|
int newLen = (int)strlen(prefix) + 32 + 2 + (sizeof(LPVOID) * 2 + 8) * 2;
|
|
*buffer = (char*)realloc(*buffer, curLen + 1 + newLen);
|
|
if (node != NULL)
|
|
{
|
|
PUCHAR h = node->guid;
|
|
sprintf(*buffer + curLen, "%s%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X (%p) (%p)\n\x00",
|
|
prefix,
|
|
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],
|
|
node->left, node->right);
|
|
char p[512];
|
|
sprintf(p, "%.*s|", (int)(INT_PTR)strlen(prefix), " ");
|
|
// print the right hand side first, as it seems to make sense when viewing the content
|
|
pivot_tree_to_string(buffer, node->right, p);
|
|
pivot_tree_to_string(buffer, node->left, p);
|
|
}
|
|
else
|
|
{
|
|
sprintf(*buffer + strlen(*buffer), "%sNULL\n", prefix);
|
|
}
|
|
}
|
|
|
|
void dbgprint_pivot_tree(PivotTree* tree)
|
|
{
|
|
char* buffer = NULL;
|
|
pivot_tree_to_string(&buffer, tree->head, " ");
|
|
if (buffer)
|
|
{
|
|
dprintf("[PIVOTTREE] contents:\n%s", buffer);
|
|
free(buffer);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
PivotTree* pivot_tree_create()
|
|
{
|
|
return (PivotTree*)calloc(1, sizeof(PivotTree));
|
|
}
|
|
|
|
DWORD pivot_tree_add_node(PivotNode* parent, PivotNode* node)
|
|
{
|
|
int cmp = memcmp(node->guid, parent->guid, sizeof(parent->guid));
|
|
|
|
if (cmp < 0)
|
|
{
|
|
if (parent->left == NULL)
|
|
{
|
|
dprintf("[PIVOTTREE] Adding node to left");
|
|
parent->left = node;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
dprintf("[PIVOTTREE] Adding node to left subtree");
|
|
return pivot_tree_add_node(parent->left, node);
|
|
}
|
|
|
|
if (parent->right == NULL)
|
|
{
|
|
dprintf("[PIVOTTREE] Adding node to right");
|
|
parent->right = node;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
dprintf("[PIVOTTREE] Adding node to right subtree");
|
|
return pivot_tree_add_node(parent->right, node);
|
|
}
|
|
|
|
DWORD pivot_tree_add(PivotTree* tree, LPBYTE guid, PivotContext* ctx)
|
|
{
|
|
PivotNode* node = (PivotNode*)calloc(1, sizeof(PivotNode));
|
|
#ifdef DEBUGTRACE
|
|
PUCHAR h = (PUCHAR)&guid[0];
|
|
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]);
|
|
#endif
|
|
|
|
memcpy(node->guid, guid, sizeof(node->guid));
|
|
node->ctx = ctx;
|
|
|
|
if (tree->head == NULL)
|
|
{
|
|
tree->head = node;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
return pivot_tree_add_node(tree->head, node);
|
|
}
|
|
|
|
PivotNode* pivot_tree_largest_node(PivotNode* node)
|
|
{
|
|
if (node == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (node->right == NULL)
|
|
{
|
|
return node;
|
|
}
|
|
return pivot_tree_largest_node(node->right);
|
|
}
|
|
|
|
PivotContext* pivot_tree_remove_node(PivotNode* parent, LPBYTE guid)
|
|
{
|
|
dprintf("[PIVOTTREE] Trying to remove from %p (%p) (%p)", parent, parent->left, parent->right);
|
|
int cmp = memcmp(guid, parent->guid, sizeof(parent->guid));
|
|
if (cmp < 0 && parent->left != NULL)
|
|
{
|
|
dprintf("[PIVOTTREE] Removing from left subtree");
|
|
int cmp = memcmp(guid, parent->left->guid, sizeof(parent->guid));
|
|
dprintf("[PIVOTTREE] Right left compare: %d", cmp);
|
|
if (cmp == 0)
|
|
{
|
|
dprintf("[PIVOTTREE] Removing right child");
|
|
PivotNode* remove = parent->left;
|
|
PivotNode* left = remove->left;
|
|
PivotNode* largest = pivot_tree_largest_node(left);
|
|
|
|
if (largest != NULL)
|
|
{
|
|
largest->right = remove->right;
|
|
parent->left = left;
|
|
}
|
|
else
|
|
{
|
|
parent->left = remove->right;
|
|
}
|
|
|
|
PivotContext* context = remove->ctx;
|
|
free(remove);
|
|
return context;
|
|
}
|
|
|
|
return pivot_tree_remove_node(parent->left, guid);
|
|
}
|
|
|
|
if (cmp > 0 && parent->right != NULL)
|
|
{
|
|
dprintf("[PIVOTTREE] Removing from right subtree");
|
|
int cmp = memcmp(guid, parent->right->guid, sizeof(parent->guid));
|
|
dprintf("[PIVOTTREE] Right subtree compare: %d", cmp);
|
|
if (cmp == 0)
|
|
{
|
|
dprintf("[PIVOTTREE] Removing right child");
|
|
PivotNode* remove = parent->right;
|
|
PivotNode* left = remove->left;
|
|
PivotNode* largest = pivot_tree_largest_node(left);
|
|
|
|
if (largest != NULL)
|
|
{
|
|
largest->right = remove->right;
|
|
parent->right = left;
|
|
}
|
|
else
|
|
{
|
|
parent->right = remove->right;
|
|
}
|
|
|
|
PivotContext* context = remove->ctx;
|
|
free(remove);
|
|
return context;
|
|
}
|
|
|
|
return pivot_tree_remove_node(parent->right, guid);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
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)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
int cmp = memcmp(guid, tree->head->guid, sizeof(tree->head->guid));
|
|
|
|
if (cmp == 0)
|
|
{
|
|
dprintf("[PIVOTTREE] Removing head node");
|
|
PivotNode* remove = tree->head;
|
|
PivotNode* left = tree->head->left;
|
|
PivotNode* largest = pivot_tree_largest_node(left);
|
|
|
|
if (largest != NULL)
|
|
{
|
|
largest->right = tree->head->right;
|
|
tree->head = left;
|
|
}
|
|
else
|
|
{
|
|
tree->head = tree->head->right;
|
|
}
|
|
|
|
PivotContext* context = remove->ctx;
|
|
free(remove);
|
|
return context;
|
|
}
|
|
|
|
dprintf("[PIVOTTREE] Removing non-head node");
|
|
return pivot_tree_remove_node(tree->head, guid);
|
|
}
|
|
|
|
PivotContext* pivot_tree_find_node(PivotNode* node, LPBYTE guid)
|
|
{
|
|
if (node == NULL)
|
|
{
|
|
dprintf("[PIVOTTREE] Current pivot node is null, bailing out");
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef DEBUGTRACE
|
|
PUCHAR h = (PUCHAR)&guid[0];
|
|
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 = node->guid;
|
|
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]);
|
|
#endif
|
|
|
|
int cmp = memcmp(guid, node->guid, sizeof(node->guid));
|
|
if (cmp == 0)
|
|
{
|
|
dprintf("[PIVOTTREE] node found");
|
|
return node->ctx;
|
|
}
|
|
|
|
if (cmp < 0)
|
|
{
|
|
dprintf("[PIVOTTREE] Searching left subtree");
|
|
return pivot_tree_find_node(node->left, guid);
|
|
}
|
|
|
|
dprintf("[PIVOTTREE] Searching right subtree");
|
|
return pivot_tree_find_node(node->right, guid);
|
|
}
|
|
|
|
PivotContext* pivot_tree_find(PivotTree* tree, LPBYTE guid)
|
|
{
|
|
dprintf("[PIVOTTREE] search tree %p, head node %p", tree, tree->head);
|
|
return pivot_tree_find_node(tree->head, guid);
|
|
}
|
|
|
|
void pivot_tree_traverse_node(PivotNode* node, PivotTreeTraverseCallback callback, LPVOID state)
|
|
{
|
|
if (node != NULL)
|
|
{
|
|
pivot_tree_traverse_node(node->left, callback, state);
|
|
callback(node->guid, node->ctx, state);
|
|
pivot_tree_traverse_node(node->right, callback, state);
|
|
}
|
|
}
|
|
|
|
void pivot_tree_traverse(PivotTree* tree, PivotTreeTraverseCallback callback, LPVOID state)
|
|
{
|
|
pivot_tree_traverse_node(tree->head, callback, state);
|
|
}
|
|
|
|
void pivot_tree_destroy_node(PivotNode* node)
|
|
{
|
|
if (node != NULL)
|
|
{
|
|
pivot_tree_destroy_node(node->left);
|
|
pivot_tree_destroy_node(node->right);
|
|
free(node);
|
|
}
|
|
}
|
|
|
|
void pivot_tree_destroy(PivotTree* tree)
|
|
{
|
|
pivot_tree_destroy_node(tree->head);
|
|
free(tree);
|
|
} |