Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Артефакт в Windows x64  (Прочитано 5619 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
zubr
Гость
« : 10-05-2014 18:31 » new

Делаю для антивирусной системы модуль эвристического анализа. Для этого из сервиса, работающего под системой, запускается специальный процесс и инжектируется в открывающиеся процессы с целью перенаправить определенные апишные функции на свой обработчик. Принцип инжекта простой - запускаемый процесс инжекта сам себя копирует в инжектируемый процесс, корректируя там релоки и вставляя код в памяти инжектируемого процесса для перенаправления на свои обработчики. Тестировал в системах Win7,8, Windows2008 server x86-x64. Вот код в котором происходит проблема:
Код:
BOOL Gl::HookProcess(DWORD idProcess, PVOID entryPoint, PWCHAR dllName, DWORD_PTR dllBaseAddress, Gl::PgFunclist funcList, WORD listCount)
{
    HMODULE hlib = NULL;
    HANDLE hpr = NULL;
    DWORD_PTR adr, BaseAddress = NULL, RemoteAddress = NULL, OldProc = NULL;
    PDWORD_PTR pRemoteAddress = NULL, pBaseAddress = NULL;
    BOOL result = FALSE;
    DWORD deltaf, oldprotect, nb;
    PVOID buf = NULL, p;

    #ifdef DBG
    PWCHAR tmp;    
    tmp = (PWCHAR)VirtualAlloc(NULL, 1000 * sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE);
    #endif

    hlib = LoadLibrary(dllName);
    if(!hlib)
    return FALSE;    

    while(1)
   {
   pBaseAddress = (PDWORD_PTR)VirtualAlloc(NULL, sizeof(DWORD_PTR), MEM_COMMIT, PAGE_READWRITE);
   if(!pBaseAddress)
   break;

          pRemoteAddress = (PDWORD_PTR)VirtualAlloc(NULL, sizeof(DWORD_PTR), MEM_COMMIT, PAGE_READWRITE);
  if(!pRemoteAddress)
  break;        

   if(!Gl::HookCode(idProcess, entryPoint, &hpr, &BaseAddress, &RemoteAddress))
  break;

          *pRemoteAddress = RemoteAddress;
          *pBaseAddress = BaseAddress;

          #ifdef DBG
          wsprintf(tmp, L"GHookCode %x %x\n", BaseAddress, RemoteAddress);
  OutputDebugString(tmp);
          #endif

          buf = VirtualAlloc(NULL, 100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

   for(int i = 0; i < listCount; i++)
  {
                  deltaf = Gl::GetDeltaFunction(hlib, funcList[i].funcName);    
                  if(!Gl::SaveOldFunction(hpr, dllBaseAddress, deltaf, &OldProc))
 continue;                      
          
                   adr = RemoteAddress + ((DWORD_PTR)(funcList[i].oldFunc) - BaseAddress);
  WriteProcessMemory(hpr, (PVOID)adr, &OldProc, sizeof(DWORD_PTR), (SIZE_T*)&nb);
                    
                  RemoteAddress = *pRemoteAddress;
                  BaseAddress = *pBaseAddress;

                  #ifdef DBG
                  wsprintf(tmp, L"GHookCode %x %x\n", BaseAddress, RemoteAddress);
         OutputDebugString(tmp);          
                 #endif            

  adr = RemoteAddress + ((DWORD_PTR)(funcList[i].newFunc) - BaseAddress);                    

                  p = buf;
                  *((BYTE*)p) = 0xE9;
          p = (PVOID)((DWORD_PTR)p + 1);          
                  *((DWORD*)p) = (DWORD)((LONG_PTR)adr - (LONG_PTR)(dllBaseAddress + deltaf + 5));

                  #ifdef DBG
                  wsprintf(tmp, L"delta %x\n", (DWORD)((LONG_PTR)adr - (LONG_PTR)(dllBaseAddress + deltaf + 5)));
         OutputDebugString(tmp);
                  #endif

  adr = dllBaseAddress + deltaf;
                                
                  VirtualProtectEx(hpr, (PVOID)adr, 10, PAGE_READWRITE, &oldprotect);
                  WriteProcessMemory(hpr, (PVOID)adr, buf, 5, (SIZE_T*)&nb);          
                  VirtualProtectEx(hpr, (PVOID)adr, 10, oldprotect, &oldprotect);

                  RemoteAddress = *pRemoteAddress;
                  BaseAddress = *pBaseAddress;
   }

             result = TRUE;
             break;
}
CWA(kernel32, FreeLibrary)(hlib);
if(pBaseAddress)
        VirtualFree(pBaseAddress, 0, MEM_RELEASE);
        if(pRemoteAddress)
        VirtualFree(pRemoteAddress, 0, MEM_RELEASE);    
        if(buf)
        VirtualFree(buf, 0, MEM_RELEASE);
if(hpr)
CloseHandle(hpr);
#ifdef DBG
if(tmp)
        VirtualFree(tmp, 0, MEM_RELEASE);          
        #endif

return result;
}
В 32-битных системах все нормально работает, в 64-битных выявилась следующая бяка:
После вызова WriteProcessMemory в x64 почему то переменные RemoteAddress и BaseAddress сбрасываются в 0. Поэтому пришлось ввести дополнительные переменные pRemoteAddress и pBaseAddress, в которых сохранять значения RemoteAddress и BaseAddress до вызова WriteProcessMemory и восстанавливать эти значения после вызова WriteProcessMemory. Причем пришлось создавать переменные из памяти процесса, а не из стека, иначе вообще код падает. Правда в процессе отключен RTL и проверка переполнения стека. Но все равно непонятно почему именно после вызова WriteProcessMemory происходит подобное.
« Последнее редактирование: 10-05-2014 18:38 от zubr » Записан
sss
Специалист

ru
Offline Offline

« Ответ #1 : 12-05-2014 14:38 » 

Интересно.. Попробуйте установить другое выравнивание данных для этих переменных.

Код: (C++)
...
#pragma pack (push)
#pragma pack (16)
 DWORD_PTR adr, BaseAddress = NULL, RemoteAddress = NULL, OldProc = NULL;
#pragma pack (pop)
...
 
Или для всего приложения..
Записан

while (8==8)
zubr
Гость
« Ответ #2 : 13-05-2014 07:22 » 

sss, спасибо за совет, будет время, попробую. Только, честно говоря, не понятна связь выравнивания переменных с работой WriteProcessMemory, которые даже в этой функции не применяются.
Надо будет еще ассемлерный код глянуть, что там компилятор создает, пока другим занят, а этот модуль отлажен и работает, поэтому пока не до него.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines