Skip to content
This repository has been archived by the owner on Jan 22, 2024. It is now read-only.

Commit

Permalink
Land #45, extapi
Browse files Browse the repository at this point in the history
  • Loading branch information
egypt committed Nov 21, 2013
2 parents 74e75f6 + 03c786b commit d71e18d
Show file tree
Hide file tree
Showing 12 changed files with 1,987 additions and 0 deletions.
446 changes: 446 additions & 0 deletions source/extensions/extapi/clipboard.c

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions source/extensions/extapi/clipboard.h
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
217 changes: 217 additions & 0 deletions source/extensions/extapi/clipboard_image.cpp
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;
}
}
26 changes: 26 additions & 0 deletions source/extensions/extapi/clipboard_image.h
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
57 changes: 57 additions & 0 deletions source/extensions/extapi/extapi.c
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;
}
45 changes: 45 additions & 0 deletions source/extensions/extapi/extapi.h
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
Loading

0 comments on commit d71e18d

Please sign in to comment.