Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Added the notion of "group packets" #75

Merged
merged 1 commit into from

4 participants

@OJ
Collaborator
OJ commented

A group packet is a special packet that is to be used as a group of TLVs that will live under another packet. Using this functionality means that we can easily nest groupings of data to arbitrary depths, which wasn't something we were able to do before easily.

The MSF side is easily capable of handling this scenario, but this side had always been lacking.

The clipboard dump code has been updated to show how this can be used.

This is based on a chat I had with egypt tonight, where we were both lamenting on the inability to have arbitrary depths of groups. This seems to solve it well enough without having to create a stack of code specific to group hierarchies.

Feedback/discussion very much welcome!

@OJ OJ Added the notion of "group packets"
A group packet is a special packet that is to be used as a group of TLVs that
will live under another packet. Using this functionality means that we can
easily nest groupings of data to arbitrary depths, which wasn't something we
were able to do before easily.

The MSF side is easily capable of handling this scenario, but this side had
always been lacking.

The clipboard dump code has been updated to show how this can be used.
95ba9b3
@OJ OJ referenced this pull request in rapid7/metasploit-framework
Merged

Modify clipboard dump to support new format from Meterpreter #3061

@metasploit-public-bot
Collaborator

Test PASSED.
Refer to this link for build results: https://ci.metasploit.com/job/GPR-MeterpreterWin/81/

@jlee-r7 jlee-r7 commented on the diff
source/common/core.c
((18 lines not shown))
+
+ memset(packet, 0, sizeof(Packet));
+
+ // we don't need to worry about the TLV header at this point
+ // so we'll ignore it
+
+ // Initialize the payload to be blank
+ packet->payload = NULL;
+ packet->payloadLength = 0;
+
+ return packet;
+ } while (0);
+
+ if (packet)
+ {
+ free(packet);
@jlee-r7 Collaborator
jlee-r7 added a note

I believe this is currently dead code, since we only break above if packet is NULL anyway.

I see the argument to leave this here anyway, though. Changes in the above block could introduce other error situations that would require freeing the packet.

@OJ Collaborator
OJ added a note

That was exactly my rationale for leaving it in there. Future-proofing FTW.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jlee-r7
Collaborator

This looks very much cleaner. In fact, other places that build group TLVs could benefit from this, particularly source/extensions/stdapi/server/net/config/interface.c

@OJ
Collaborator
OJ commented

I can think of quite a few other places where this can be used to make things not only more readable but reduce the amount of data transferred. Reducing code is always a win too. Constructing arrays of TLVs in the way we had to do before felt like it was prone to errors.

@todb-r7 todb-r7 referenced this pull request from a commit in todb-r7/meterpreter
@todb-r7 todb-r7 Land #75, adds Group Packets to Meterpreter 6601560
@todb-r7 todb-r7 referenced this pull request from a commit in todb-r7/metasploit-framework
@todb-r7 todb-r7 Land #3061, enhance clipboard dump
This depends on rapid7/meterpreter#75 to function
04b5d71
@todb-r7 todb-r7 referenced this pull request from a commit in todb-r7/metasploit-framework
@todb-r7 todb-r7 Refresh binaries for Meterpreter
This includes:

rapid7/meterpreter#69
rapid7/meterpreter#70
rapid7/meterpreter#75
rapid7/meterpreter#77
rapid7/meterpreter#78

As of commit: 45bcbd13a1e0215647f6a61631652b686931bba8
05436dc
@todb-r7 todb-r7 referenced this pull request from a commit
@todb-r7 todb-r7 Land #80, lots of @OJ PRs
This lands:

rapid7/meterpreter#69
rapid7/meterpreter#70
rapid7/meterpreter#75
rapid7/meterpreter#77
rapid7/meterpreter#78

All have been tested sufficiently, and once this lands, the binaries as
well as the library and module updates represented by
rapid7/metasploit-framework#3122 will also land.
5addac7
@todb-r7 todb-r7 merged commit 95ba9b3 into from
@bcook-r7 bcook-r7 referenced this pull request from a commit in bcook-r7/metasploit-payloads
@todb-r7 todb-r7 Land #80, lots of @OJ PRs
This lands:

rapid7/meterpreter#69
rapid7/meterpreter#70
rapid7/meterpreter#75
rapid7/meterpreter#77
rapid7/meterpreter#78

All have been tested sufficiently, and once this lands, the binaries as
well as the library and module updates represented by
rapid7/metasploit-framework#3122 will also land.
4fb765e
@todb-r7 todb-r7 referenced this pull request from a commit in rapid7/metasploit-payloads
@todb-r7 todb-r7 Land #80, lots of @OJ PRs
This lands:

rapid7/meterpreter#69
rapid7/meterpreter#70
rapid7/meterpreter#75
rapid7/meterpreter#77
rapid7/meterpreter#78

All have been tested sufficiently, and once this lands, the binaries as
well as the library and module updates represented by
rapid7/metasploit-framework#3122 will also land.
369e833
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 4, 2014
  1. @OJ

    Added the notion of "group packets"

    OJ authored
    A group packet is a special packet that is to be used as a group of TLVs that
    will live under another packet. Using this functionality means that we can
    easily nest groupings of data to arbitrary depths, which wasn't something we
    were able to do before easily.
    
    The MSF side is easily capable of handling this scenario, but this side had
    always been lacking.
    
    The clipboard dump code has been updated to show how this can be used.
This page is out of date. Refresh to see the latest.
View
55 source/common/core.c
@@ -214,6 +214,61 @@ Packet *packet_create( PacketTlvType type, LPCSTR method )
}
/*!
+ * @brief Create a packet that is used to contain a subgroup.
+ * @returns An instance of a packet to use as a group container.
+ * @remarks Group packets can be used to arbitrarily nest groupings prior to
+ * sending the packet to the client.
+ */
+Packet* packet_create_group()
+{
+ Packet* packet = NULL;
+ do
+ {
+ if (!(packet = (Packet*)malloc(sizeof(Packet))))
+ {
+ break;
+ }
+
+ memset(packet, 0, sizeof(Packet));
+
+ // we don't need to worry about the TLV header at this point
+ // so we'll ignore it
+
+ // Initialize the payload to be blank
+ packet->payload = NULL;
+ packet->payloadLength = 0;
+
+ return packet;
+ } while (0);
+
+ if (packet)
+ {
+ free(packet);
@jlee-r7 Collaborator
jlee-r7 added a note

I believe this is currently dead code, since we only break above if packet is NULL anyway.

I see the argument to leave this here anyway, though. Changes in the above block could introduce other error situations that would require freeing the packet.

@OJ Collaborator
OJ added a note

That was exactly my rationale for leaving it in there. Future-proofing FTW.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ }
+ return NULL;
+}
+
+/*!
+ * @brief Add a group packet to the parent packet.
+ * @param packet Pointer to the container packet that the group is to be added to.
+ * @param type The type of group packet being added.
+ * @param groupPacket the packet containing the group data (created by `packet_create_group`).
+ * @returns Indication of success or failure.
+ * @remarks The function calls `packet_destroy` on the `groupPacket` if adding the packet succeeds.
+ */
+DWORD packet_add_group(Packet* packet, TlvType type, Packet* groupPacket)
+{
+ DWORD result = packet_add_tlv_raw(packet, type, groupPacket->payload, groupPacket->payloadLength);
+ if (result == ERROR_SUCCESS)
+ {
+ packet_destroy(groupPacket);
+ return ERROR_SUCCESS;
+ }
+
+ return result;
+}
+
+/*!
* @brief Create a response packet from a request.
* @details Create a response packet from a request, referencing the requestors
* message identifier.
View
2  source/common/core.h
@@ -206,9 +206,11 @@ typedef struct
*/
LINKAGE Packet *packet_create(PacketTlvType type, LPCSTR method);
LINKAGE Packet *packet_create_response(Packet *packet);
+LINKAGE Packet* packet_create_group();
LINKAGE Packet *packet_duplicate(Packet *packet);
LINKAGE VOID packet_destroy(Packet *packet);
+LINKAGE DWORD packet_add_group(Packet* packet, TlvType type, Packet* groupPacket);
LINKAGE DWORD packet_add_tlv_string(Packet *packet, TlvType type, LPCSTR str);
LINKAGE DWORD packet_add_tlv_wstring(Packet *packet, TlvType type, LPCWSTR str);
LINKAGE DWORD packet_add_tlv_uint(Packet *packet, TlvType type, UINT val);
View
53 source/extensions/extapi/clipboard.c
@@ -339,47 +339,32 @@ VOID timestamp_to_string(SYSTEMTIME* pTime, char buffer[40])
VOID dump_clipboard_capture(Packet* pResponse, ClipboardCapture* pCapture, BOOL bCaptureImageData)
{
ClipboardFile* pFile;
- Tlv entries[4];
+ Packet* group = packet_create_group();
+ TlvType groupType;
+ Packet* file = NULL;
char timestamp[40];
dprintf("[EXTAPI CLIPBOARD] Dumping clipboard capture");
- memset(entries, 0, sizeof(entries));
memset(timestamp, 0, sizeof(timestamp));
timestamp_to_string(&pCapture->stCaptureTime, timestamp);
- entries[0].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_TIMESTAMP;
- entries[0].header.length = lstrlenA(timestamp) + 1;
- entries[0].buffer = (PUCHAR)timestamp;
+ packet_add_tlv_string(group, TLV_TYPE_EXT_CLIPBOARD_TYPE_TIMESTAMP, timestamp);
dprintf("[EXTAPI CLIPBOARD] Timestamp added: %s", timestamp);
switch (pCapture->captureType)
{
case CapText:
dprintf("[EXTAPI CLIPBOARD] Dumping text %s", pCapture->lpText);
- entries[1].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT_CONTENT;
- entries[1].buffer = (PUCHAR)(pCapture->lpText ? pCapture->lpText : "(null - clipboard was cleared)");
- entries[1].header.length = lstrlenA((char*)entries[1].buffer) + 1;
-
- packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT, entries, 2);
- dprintf("[EXTAPI CLIPBOARD] Text added to packet");
+ packet_add_tlv_string(group, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT_CONTENT, (PUCHAR)(pCapture->lpText ? pCapture->lpText : "(null - clipboard was cleared)"));
+ groupType = TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT;
break;
case CapImage:
dprintf("[EXTAPI CLIPBOARD] Dumping image %ux%x", pCapture->lpImage->dwWidth, pCapture->lpImage->dwHeight);
- entries[1].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMX;
- entries[1].header.length = sizeof(DWORD);
- entries[1].buffer = (PUCHAR)&pCapture->lpImage->dwWidth;
-
- entries[2].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMY;
- entries[2].header.length = sizeof(DWORD);
- entries[2].buffer = (PUCHAR)&pCapture->lpImage->dwHeight;
-
- entries[3].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DATA;
- entries[3].header.length = pCapture->lpImage->dwImageSize;
- entries[3].buffer = (PUCHAR)pCapture->lpImage->lpImageContent;
-
- packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG, entries, bCaptureImageData && pCapture->lpImage->lpImageContent ? 4 : 3);
- dprintf("[EXTAPI CLIPBOARD] Image added to packet");
+ packet_add_tlv_uint(group, TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMX, pCapture->lpImage->dwWidth);
+ packet_add_tlv_uint(group, TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMY, pCapture->lpImage->dwHeight);
+ packet_add_tlv_raw(group, TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DATA, pCapture->lpImage->lpImageContent, pCapture->lpImage->dwImageSize);
+ groupType = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG;
break;
case CapFiles:
pFile = pCapture->lpFiles;
@@ -387,25 +372,25 @@ VOID dump_clipboard_capture(Packet* pResponse, ClipboardCapture* pCapture, BOOL
while (pFile)
{
dprintf("[EXTAPI CLIPBOARD] Dumping file %p", pFile);
+ file = packet_create_group();
dprintf("[EXTAPI CLIPBOARD] Adding path %s", pFile->lpPath);
- entries[1].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME;
- entries[1].header.length = lstrlenA(pFile->lpPath) + 1;
- entries[1].buffer = (PUCHAR)pFile->lpPath;
+ packet_add_tlv_string(file, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME, pFile->lpPath);
dprintf("[EXTAPI CLIPBOARD] Adding size %llu", htonq(pFile->qwSize));
- entries[2].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE;
- entries[2].header.length = sizeof(QWORD);
- entries[2].buffer = (PUCHAR)&pFile->qwSize;
+ packet_add_tlv_qword(file, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE, pFile->qwSize);
dprintf("[EXTAPI CLIPBOARD] Adding group");
- packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE, entries, 3);
+ packet_add_group(group, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE, file);
pFile = pFile->pNext;
dprintf("[EXTAPI CLIPBOARD] Moving to next");
}
+ groupType = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILES;
break;
}
+
+ packet_add_group(pResponse, groupType, group);
}
/*!
@@ -635,8 +620,8 @@ DWORD capture_clipboard(BOOL bCaptureImageData, ClipboardCapture** ppCapture)
pCapture->captureType = CapImage;
pCapture->lpImage = (ClipboardImage*)malloc(sizeof(ClipboardImage));
memset(pCapture->lpImage, 0, sizeof(ClipboardImage));
- pCapture->lpImage->dwWidth = htonl(lpBI->bmiHeader.biWidth);
- pCapture->lpImage->dwHeight = htonl(lpBI->bmiHeader.biHeight);
+ pCapture->lpImage->dwWidth = lpBI->bmiHeader.biWidth;
+ pCapture->lpImage->dwHeight = lpBI->bmiHeader.biHeight;
// throw together a basic guess for this, it doesn't have to be exact.
pCapture->dwSize = lpBI->bmiHeader.biWidth * lpBI->bmiHeader.biHeight * 4;
View
1  source/extensions/extapi/extapi.h
@@ -40,6 +40,7 @@
#define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 41)
#define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 42)
#define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 43)
+#define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILES MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 44)
#define TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 45)
#define TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMX MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 46)
Something went wrong with that request. Please try again.