This repository has been archived by the owner on Jan 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 145
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
1,987 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/*! | ||
* @file clipboard.h | ||
* @brief Declarations for clipboard interaction functionality | ||
*/ | ||
#ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_H | ||
#define _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_H | ||
|
||
DWORD request_clipboard_set_data(Remote *remote, Packet *packet); | ||
DWORD request_clipboard_get_data(Remote *remote, Packet *packet); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
/*! | ||
* @file clipboard_image.cpp | ||
* @brief Definitions for clipboard image handling functionality | ||
* @remark This is a C++ file because it uses GDI+ behind the scenes. This is because it's super | ||
* easy to do image encoding and prevents us from having to include the massive JPG lib. | ||
* It's not late-bound using LoadLibrary due to the fact that doing that with C++ stuff | ||
* is nothing short of painful. | ||
*/ | ||
extern "C" { | ||
#include "extapi.h" | ||
#include "clipboard_image.h" | ||
} | ||
#include <GdiPlus.h> | ||
|
||
/*! | ||
* @brief Get the Class ID of an encoder which supports encoding to the specified MIME type. | ||
* @param mimeType The wide-string formatting MIME type identifier. | ||
* @param pClsId Pointer to the \c CLSID structure that will receive the Class ID. | ||
* @returns Indication of success or failure. | ||
* @retval ERROR_SUCCESS The Class ID was extracted successfully. | ||
* @retval ERROR_NOT_FOUND The Class ID was not found. | ||
* @retval Otherwise The relevant error code. | ||
*/ | ||
DWORD get_encoder_clsid(WCHAR *mimeType, CLSID * pClsId) | ||
{ | ||
using namespace Gdiplus; | ||
|
||
DWORD dwResult = ERROR_NOT_FOUND; | ||
ImageCodecInfo* pImageCodecInfo = NULL; | ||
|
||
do | ||
{ | ||
UINT numEncoders; | ||
UINT size; | ||
if (GetImageEncodersSize(&numEncoders, &size) != Ok) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to get encoders array size.", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
if (size == 0) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] No encoders found.", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
if ((pImageCodecInfo = (ImageCodecInfo*)malloc(size)) == NULL) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Couldn't allocate memory for ImageCodeInfo", ERROR_OUTOFMEMORY); | ||
} | ||
|
||
if (GetImageEncoders(numEncoders, size, pImageCodecInfo) != Ok) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to get encoders.", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
for (UINT i = 0; i < numEncoders; ++i) { | ||
if (wcscmp(pImageCodecInfo[i].MimeType, mimeType) == 0) { | ||
// Image encoder for the MIME type found, so copy the Class ID... | ||
memcpy_s(pClsId, sizeof(CLSID), &pImageCodecInfo[i].Clsid, sizeof(CLSID)); | ||
|
||
// .. and finish up. | ||
dwResult = ERROR_SUCCESS; | ||
break; | ||
} | ||
} | ||
} while (0); | ||
|
||
if (pImageCodecInfo != NULL) { | ||
free(pImageCodecInfo); | ||
} | ||
|
||
return dwResult; | ||
} | ||
|
||
extern "C" { | ||
|
||
/*! | ||
* @brief Calculate the size of the specified bitmap information header. | ||
* @param lpBI Pointer to the \cBITMAPINFO structure that contains the detail of the bitmap. | ||
* In the case of the clipboard, this is the CF_DIB data. | ||
* @param bRGB Set to \c TRUE if the colors are in RBG format, \c FALSE otherwise. | ||
* @remark This function is necessary due to the fact that the information | ||
* stored on the clipboard can't be handled properly unless we know | ||
* where in memory the DIB bits are. | ||
* @returns The size of the bitmap information header. | ||
*/ | ||
DWORD get_bitmapinfo_size(const LPBITMAPINFO lpBI, BOOL bRGB) | ||
{ | ||
DWORD dwColors, dwSize; | ||
|
||
if (lpBI->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { | ||
const BITMAPCOREHEADER* core = (const BITMAPCOREHEADER*)lpBI; | ||
|
||
dwColors = core->bcBitCount <= 8 | ||
? 1 << core->bcBitCount | ||
: 0; | ||
|
||
dwSize = sizeof(BITMAPCOREHEADER); | ||
} | ||
else { | ||
dwColors = lpBI->bmiHeader.biClrUsed; | ||
|
||
if (!dwColors && lpBI->bmiHeader.biBitCount <= 8) { | ||
dwColors = 1 << lpBI->bmiHeader.biBitCount; | ||
} | ||
|
||
dwSize = max(lpBI->bmiHeader.biSize, | ||
(lpBI->bmiHeader.biCompression == BI_BITFIELDS ? 3 : 0) | ||
* sizeof(DWORD)+sizeof(BITMAPINFOHEADER)); | ||
} | ||
|
||
return dwSize + dwColors * (bRGB ? sizeof(RGBTRIPLE) : sizeof(WORD)); | ||
} | ||
|
||
/*! | ||
* @brief Convert the given bitmap data into a JPEG image of the specified quality. | ||
* @param lpBI Pointer to the \cBITMAPINFO structure that contains the detail of the bitmap. | ||
* In the case of the clipboard, this is the CF_DIB data. | ||
* @param lpDIB Pointer to the DIB bytes that make up the image data. | ||
* @param ulQuality Quality of the resulting JPG image. | ||
* @param pImage Pointer to the image structure that will receive the image data | ||
* @retval ERROR_SUCCESS The Class ID was extracted successfully. | ||
* @retval Otherwise The relevant error code. | ||
* @remark This functionality uses GDI+ to convert the image to a JPG. | ||
*/ | ||
DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage) | ||
{ | ||
using namespace Gdiplus; | ||
|
||
HRESULT hRes = S_OK; | ||
DWORD dwResult = ERROR_SUCCESS; | ||
ULONG_PTR gdiPlusToken = 0; | ||
Bitmap* pBitmap = NULL; | ||
GdiplusStartupInput gdiStartupInput; | ||
IStream* pStream = NULL; | ||
|
||
// set this to NULL up front so that we can keep track of allocations; | ||
pImage->pImageBuffer = NULL; | ||
pImage->dwImageBufferSize = 0; | ||
|
||
do | ||
{ | ||
if (GdiplusStartup(&gdiPlusToken, &gdiStartupInput, NULL) != Ok) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to initialize GdiPlus", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
CLSID jpegClsid; | ||
dprintf("[EXTAPI CLIPIMG] Attempting to get the jpg class id"); | ||
if (get_encoder_clsid(L"image/jpeg", &jpegClsid) != ERROR_SUCCESS) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to find an appropriate image encoder", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
if ((pBitmap = new Bitmap(lpBI, lpDIB)) == NULL) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to create bitmap instance", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
EncoderParameters encParams; | ||
encParams.Count = 1; | ||
encParams.Parameter[0].NumberOfValues = 1; | ||
encParams.Parameter[0].Guid = EncoderQuality; | ||
encParams.Parameter[0].Type = EncoderParameterValueTypeLong; | ||
encParams.Parameter[0].Value = &ulQuality; | ||
|
||
if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) != S_OK) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to create stream", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
if (pBitmap->Save(pStream, &jpegClsid, &encParams) != Ok) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to save image to stream", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
STATSTG stat; | ||
if (pStream->Stat(&stat, STATFLAG_NONAME) != S_OK) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to get image stat", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
// if the image requires the quadpart, then we're in trouble anyway! | ||
pImage->dwImageBufferSize = stat.cbSize.LowPart; | ||
if ((pImage->pImageBuffer = (LPBYTE)malloc(pImage->dwImageBufferSize)) == NULL) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to allocate memory for the JPEG", ERROR_OUTOFMEMORY); | ||
} | ||
|
||
ULARGE_INTEGER pos; | ||
LARGE_INTEGER zero; | ||
zero.QuadPart = 0; | ||
pos.QuadPart = 0; | ||
if (pStream->Seek(zero, STREAM_SEEK_SET, &pos) != S_OK) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed set stream position", ERROR_FUNCTION_FAILED); | ||
} | ||
|
||
ULONG bytesRead = 0; | ||
if ((hRes = pStream->Read(pImage->pImageBuffer, pImage->dwImageBufferSize, &bytesRead) != S_OK)) { | ||
dprintf("[EXTAPI CLIPIMG] Failed to read image data from stream: %u %x", hRes, hRes); | ||
dwResult = ERROR_FUNCTION_FAILED; | ||
break; | ||
} | ||
|
||
if (bytesRead != pImage->dwImageBufferSize) { | ||
BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to read image data from stream", ERROR_FUNCTION_FAILED); | ||
} | ||
} while (0); | ||
|
||
if (dwResult != ERROR_SUCCESS && pImage->pImageBuffer != NULL) { | ||
free(pImage->pImageBuffer); | ||
pImage->pImageBuffer = NULL; | ||
} | ||
|
||
if (pStream != NULL) { | ||
pStream->Release(); | ||
} | ||
|
||
if (pBitmap != NULL) { | ||
delete pBitmap; | ||
} | ||
|
||
if (gdiPlusToken != 0) { | ||
GdiplusShutdown(gdiPlusToken); | ||
} | ||
|
||
return dwResult; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/*! | ||
* @file clipboard_image.h | ||
* @brief Declarations for clipboard image handling functionality | ||
*/ | ||
#ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_IMAGE_H | ||
#define _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_IMAGE_H | ||
|
||
typedef struct _ConvertedImage | ||
{ | ||
/*! | ||
* @brief Pointer to a pointer which will receive the JPEG image data buffer. | ||
* This value is allocated using \c malloc prior to returning. If after | ||
* calling this function the value is non-NULL the caller must call | ||
* \c free to release this memory. | ||
*/ | ||
PBYTE pImageBuffer; | ||
/*! | ||
* @brief The size of the \c pImageBuffer buffer. | ||
*/ | ||
DWORD dwImageBufferSize; | ||
} ConvertedImage; | ||
|
||
DWORD get_bitmapinfo_size(const LPBITMAPINFO lpBI, BOOL bRGB); | ||
DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/*! | ||
* @file extapi.h | ||
* @brief Entry point and intialisation definitions for the extended API extension. | ||
*/ | ||
#include "../../common/common.h" | ||
|
||
#include "../../ReflectiveDLLInjection/DelayLoadMetSrv.h" | ||
// include the Reflectiveloader() function, we end up linking back to the metsrv.dll's Init function | ||
// but this doesnt matter as we wont ever call DLL_METASPLOIT_ATTACH as that is only used by the | ||
// second stage reflective dll inject payload and not the metsrv itself when it loads extensions. | ||
#include "../../ReflectiveDLLInjection/ReflectiveLoader.c" | ||
|
||
#include "window.h" | ||
#include "service.h" | ||
#include "clipboard.h" | ||
|
||
// this sets the delay load hook function, see DelayLoadMetSrv.h | ||
EnableDelayLoadMetSrv(); | ||
|
||
/*! @brief List of commands that the extended API extension providers. */ | ||
Command customCommands[] = | ||
{ | ||
COMMAND_REQ("extapi_window_enum", request_window_enum), | ||
COMMAND_REQ("extapi_service_enum", request_service_enum), | ||
COMMAND_REQ("extapi_service_query", request_service_query), | ||
COMMAND_REQ("extapi_clipboard_get_data", request_clipboard_get_data), | ||
COMMAND_REQ("extapi_clipboard_set_data", request_clipboard_set_data), | ||
COMMAND_TERMINATOR | ||
}; | ||
|
||
/*! | ||
* @brief Initialize the server extension | ||
* @details Registers all the extended API commands. | ||
* @param remote Pointer to the \c Remote initialising the extension. | ||
* @returns Always returns \c ERROR_SUCCESS. | ||
*/ | ||
DWORD __declspec(dllexport) InitServerExtension(Remote *remote) | ||
{ | ||
hMetSrv = remote->hMetSrv; | ||
|
||
command_register_all(customCommands); | ||
|
||
return ERROR_SUCCESS; | ||
} | ||
|
||
/*! | ||
* @brief Deinitialize the server extension. | ||
* @details Unregisters all the extended API commands. | ||
* @param remote Pointer to the \c Remote destroying the extension. | ||
* @returns Always returns \c ERROR_SUCCESS. | ||
*/ | ||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote) | ||
{ | ||
command_deregister_all(customCommands); | ||
|
||
return ERROR_SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/*! | ||
* @file extapi.h | ||
* @brief Entry point and intialisation declarations for the extended API extension. | ||
*/ | ||
#ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_EXTAPI_H | ||
#define _METERPRETER_SOURCE_EXTENSION_EXTAPI_EXTAPI_H | ||
|
||
#include "../../common/common.h" | ||
|
||
#define TLV_TYPE_EXTENSION_EXTAPI 0 | ||
|
||
#define TLV_TYPE_EXT_WINDOW_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 1) | ||
#define TLV_TYPE_EXT_WINDOW_ENUM_PID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 2) | ||
#define TLV_TYPE_EXT_WINDOW_ENUM_HANDLE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 3) | ||
#define TLV_TYPE_EXT_WINDOW_ENUM_TITLE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 4) | ||
#define TLV_TYPE_EXT_WINDOW_ENUM_INCLUDEUNKNOWN MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 5) | ||
|
||
#define TLV_TYPE_EXT_SERVICE_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 10) | ||
#define TLV_TYPE_EXT_SERVICE_ENUM_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 11) | ||
#define TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 12) | ||
#define TLV_TYPE_EXT_SERVICE_ENUM_PID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 13) | ||
#define TLV_TYPE_EXT_SERVICE_ENUM_STATUS MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 14) | ||
#define TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 15) | ||
|
||
#define TLV_TYPE_EXT_SERVICE_QUERY_STARTTYPE MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 20) | ||
#define TLV_TYPE_EXT_SERVICE_QUERY_DISPLAYNAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 21) | ||
#define TLV_TYPE_EXT_SERVICE_QUERY_STARTNAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 22) | ||
#define TLV_TYPE_EXT_SERVICE_QUERY_PATH MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 23) | ||
#define TLV_TYPE_EXT_SERVICE_QUERY_LOADORDERGROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 24) | ||
#define TLV_TYPE_EXT_SERVICE_QUERY_INTERACTIVE MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 25) | ||
#define TLV_TYPE_EXT_SERVICE_QUERY_DACL MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 26) | ||
|
||
#define TLV_TYPE_EXT_CLIPBOARD_DOWNLOAD MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 35) | ||
|
||
#define TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 40) | ||
#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_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) | ||
#define TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMY MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 47) | ||
#define TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DATA MAKE_CUSTOM_TLV(TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 48) | ||
|
||
#endif |
Oops, something went wrong.