VEH+windows 7

Тема в разделе "WASM.WIN32", создана пользователем float, 30 май 2011.

  1. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    В общем я использую для перехвата кода дебаговые регистры. На хп сп3 все хорошо и просто. В DLL_PROCESS_ATTACH я делаю AddVectoredExceptionHandler(1,veh) и запускаю поток который ставит дебаг регистры для каждого потока(на всякий случай) хотя все перехваты срабатывают из основного потока.

    В 7ке происходит следующее:
    перехваты не срабатывают вообще, но сразу после AddVectoredExceptionHandler(1,veh) при вызове DebugBreak() перехват срабатывает. В чем может быть проблема? Приложение одно и то же, разница только в ос.
     
  2. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    Когда длл подгружается в процесс? не через appinit_dll случайно?
     
  3. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    нет, обычный инжект через CreateRemoteThread, когда потоки приложения уже работают
     
  4. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    основной поток, в котором срабатывают hbps - это основной поток процесса, в который производится инжект?
    а не пробовали повторить ситуацию в дебаггере? поставить hbp и посмотреть, сработает ли?
     
  5. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    да. Вот код который перечисляет все потоки:

    Код (Text):
    1.         HANDLE th = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,GetCurrentProcessId());
    2.        
    3.         THREADENTRY32 t = {0};
    4.         t.dwSize = sizeof(THREADENTRY32);
    5.  
    6.         Thread32First(th,&t);
    7.         do
    8.         {
    9.             if(t.th32OwnerProcessID!=GetCurrentProcessId())
    10.                 continue;
    11.             HANDLE h;
    12.             hookthread(h = OpenThread(THREAD_QUERY_INFORMATION|THREAD_GET_CONTEXT|THREAD_SET_CONTEXT,false,t.th32ThreadID));
    13.             CloseHandle(h);
    14.         } while (Thread32Next(th,&t));
    ну естественно в винде 7, в ольке хардварные брейкпойнты работают. Может там есть какая-то особенность при установке?
    я задействовал 4 слота. в Dr7 вписал следующее: (1<<0)|(1<<2)|(1<<4)|(1<<6)
     
  6. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    Глупо звучит, но отладочные привилегии Вы выставили? Проверки ошибок я не наблюдаю.
     
  7. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    нет, я конечно попробую, но у меня в принципе 1 раз ловится сразу после AddVectoredExceptionHandler. Проверил отладчиком - никто не перебивает мой VEH.
     
  8. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    а как код ставит брекпоинты? hookthread покажите?
     
  9. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    нашел проблему. Оказалось, что в ХР можно создавать потоки из DllMain, а в 7 нельзя. Это можно как-то обойти?
     
  10. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    конечно можно. в inject dll сделайте экспортируемую функцию Start с сигнатурой HRESULT (STDMETHODCALLTYPE *PFNSTART)(DWORD), и повторите трюк аналогичный удалённому запуску LoadLibrary. Авторство функции RemoteGetProcAddress не моё

    Код (Text):
    1.     DWORD dwThreadId;
    2.     HRESULT hr = Common::InjectDll(
    3.         dwProcessId, lpszDllPath, &dwThreadId, msWait, hTargetProcess.get());
    4.     if (FAILED(hr)) return hr;
    5.  
    6.     // Get the HMODULE of the injected library
    7.     std::vector< ::MODULEENTRY32> vModules;
    8.     hr = Common::ThGetProcessModules(vModules, dwProcessId);
    9.     if (FAILED(hr)) return hr;
    10.  
    11.     std::vector< ::MODULEENTRY32>::const_iterator pme =
    12.         std::find_if(vModules.begin(), vModules.end(), Common::CIsSameModulePath(lpszDllPath));
    13.     if (vModules.end() == pme)
    14.     {
    15.         WRITE_MSG(L"Module " << lpszDllPath << L" isn't found");
    16.         return E_NOTFOUND;
    17.     }
    18.  
    19.     // Get address of Start function in the injected process's address space
    20.     // exact signature is:
    21.     //typedef HRESULT (STDCALLMETHODTYPE *PFNSTART)(DWORD msWait);
    22.     HMODULE hMod = pme->hModule;
    23.     PTHREAD_START_ROUTINE pfnStart = reinterpret_cast<PTHREAD_START_ROUTINE>(
    24.         Common::RemoteGetProcAddress(hTargetProcess.get(), hMod, "Start"));
    25.     if (!pfnStart) return HRESULT_FROM_WIN32(::GetLastError());
    26.  
    27.     // Remote call Start function
    28.     HANDLE hrawRemoteThread = ::CreateRemoteThread(hTargetProcess.get(), NULL, 0,
    29.         pfnStart, &msWait, 0, &dwThreadId);
    30.     if (!hrawRemoteThread) return HRESULT_FROM_WIN32(::GetLastError());
    31.  
    32.     boost::shared_ptr<void> hRemoteThread(hrawRemoteThread, &::CloseHandle);
    33.  
    34.     // Wait for Start execution completion
    35.     hr =Common::GetWaitErrorCode( ::WaitForSingleObject(hRemoteThread.get(), msWait));
    36.     if (FAILED(hr)) return hr;
    37.  
    38.     // Get remote thread exit code
    39.     DWORD dwExitCode;
    40.     if (! ::GetExitCodeThread(hRemoteThread.get(), &dwExitCode))
    41.         return HRESULT_FROM_WIN32( ::GetLastError());
    42.     if (STILL_ACTIVE == dwExitCode) return E_UNEXPECTED;
    43.  
    44.     return S_OK;
    45.  
    46. //  
    47. //  FUNCTION:     void* RemoteGetProcAddress(HANDLE , HMODULE, const char* )
    48. //
    49. //  PARAMETERS:   [IN] hProcess  - описатель процесса
    50. //                [IN] hLib      - HMODULE dll в заданном процессе
    51. //                [IN] name      - имя функции
    52. //
    53. //  RETURN VALUE: адрес функции в заданном процессе или NULL
    54. //
    55. //  REVISION:     17.09.2004  Сергей Холодилов
    56. //
    57. //  PURPOSE:      Находит нужную функцию в указанной dll в указанном процессе
    58. //
    59. //  COMMENTS:    
    60. //
    61. void *STDMETHODCALLTYPE RemoteGetProcAddress(HANDLE hProcess, HMODULE hLib, const char* name)
    62. {
    63.     // Нам нужен именно адрес загрузки! А результат работы
    64.     // LoadLibrary бывает иногда неожиданным..
    65.     char* baseAddress = reinterpret_cast<char*>
    66.                              (reinterpret_cast<DWORD>(hLib) & 0xFFFF0000);
    67.  
    68.     // Смещение секции экспорта
    69.     int export_offset;
    70.     HRESULT hr = GetExportSectionRVA(hProcess, baseAddress, &export_offset);
    71.     if (FAILED(hr))
    72.     {
    73.         // Какие-то проблемы с экспортом
    74.         return NULL;
    75.     }
    76.  
    77.     // Читаем заголовок секции экспорта
    78.     IMAGE_EXPORT_DIRECTORY ied;
    79.     if (!::ReadProcessMemory(
    80.             hProcess,
    81.             baseAddress + export_offset,
    82.             &ied,
    83.             sizeof(IMAGE_EXPORT_DIRECTORY),
    84.             0))
    85.     {
    86.         // Не судьба
    87.         return NULL;
    88.     }
    89.  
    90.     // Индекс в массиве функций
    91.     WORD funcIndex = -1;
    92.  
    93.     if (reinterpret_cast<DWORD_PTR>(name) > 0x0000ffff)
    94.     {
    95.         // Функция экспортируется по имени. Ищем имя
    96.         int nameIndex;
    97.         hr = FindName(
    98.                             hProcess,
    99.                             baseAddress,
    100.                             ied.AddressOfNames,
    101.                             ied.NumberOfNames,
    102.                             name,
    103.                             &nameIndex);
    104.  
    105.         if (FAILED(hr))
    106.         {
    107.             // Такой функции нет
    108.             return NULL;
    109.         }
    110.  
    111.         // Читаем индекс (они двухбайтные!!!)
    112.         if (!::ReadProcessMemory(
    113.                 hProcess,
    114.                 baseAddress + ied.AddressOfNameOrdinals
    115.                     + nameIndex * sizeof(WORD),
    116.                 &funcIndex,
    117.                 sizeof(funcIndex),
    118.                 0))
    119.         {
    120.             return NULL;
    121.         }
    122.     }
    123.     else
    124.     {
    125.         // Функция экспортируется по ординалу
    126.         WORD funcOrdinal = static_cast<WORD>(reinterpret_cast<DWORD>(name));
    127.  
    128.         if ((funcOrdinal < ied.Base)
    129.          || (funcOrdinal >= ied.Base + ied.NumberOfFunctions))
    130.         {
    131.             // Такой функции нет
    132.             return NULL;
    133.         }
    134.  
    135.         funcIndex = static_cast<WORD>(funcOrdinal - ied.Base);
    136.     }
    137.  
    138. #ifdef __BORLANDC__
    139. #pragma option push -w-8008
    140. #endif  // __BORLANDC__
    141.     if ((funcIndex < 0) || (funcIndex >= ied.NumberOfFunctions))
    142. #ifdef __BORLANDC__
    143. #pragma option pop
    144. #endif  // __BORLANDC__
    145.     {
    146.         // Такой функции нет
    147.         return NULL;
    148.     }
    149.  
    150.     // Читаем адрес
    151.     DWORD funcRVA;
    152.     if (!::ReadProcessMemory(
    153.             hProcess,
    154.             baseAddress + ied.AddressOfFunctions + funcIndex * sizeof(DWORD),
    155.             &funcRVA,
    156.             sizeof(funcRVA),
    157.             0))
    158.     {
    159.         return NULL;
    160.     }
    161.  
    162.     // Результат это базовый адрес + RVA
    163.     return (baseAddress + funcRVA);
    164. }
    165.  
    166. // Определяет RVA секции экспорта
    167. HRESULT STDMETHODCALLTYPE GetExportSectionRVA(HANDLE hProcess, const char* baseAddress, int *iRVA)
    168. {
    169.     if (!iRVA) return E_POINTER;
    170.  
    171.     // Читаем DOS-заголовок
    172.     IMAGE_DOS_HEADER dos_header;
    173.    
    174.     if (!::ReadProcessMemory(
    175.             hProcess,
    176.             baseAddress,
    177.             &dos_header,
    178.             sizeof(IMAGE_DOS_HEADER),
    179.             0))
    180.     {
    181.         return HRESULT_FROM_WIN32(::GetLastError());
    182.     }
    183.  
    184.     // Читаем PE-заголовок
    185.     IMAGE_NT_HEADERS pe_header;
    186.  
    187.     if (!::ReadProcessMemory(
    188.             hProcess,
    189.             baseAddress + dos_header.e_lfanew,
    190.             &pe_header,
    191.             sizeof(IMAGE_NT_HEADERS),
    192.             0))
    193.     {
    194.         return HRESULT_FROM_WIN32(::GetLastError());
    195.     }
    196.  
    197.     // Смещение секции экспорта
    198.     *iRVA = pe_header.OptionalHeader.DataDirectory
    199.                         [IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    200.     return S_OK;
    201. }
    202.  
    203. // Перебирает массив имён функций, ищет там заданное имя
    204. HRESULT STDMETHODCALLTYPE FindName(
    205.                     HANDLE hProcess,
    206.                     const char* baseAddress,
    207.                     DWORD AddressOfNames,
    208.                     DWORD count,
    209.                     const char* name,
    210.                     int *pnIndex)
    211. {
    212.     if (!pnIndex) return E_POINTER;
    213.  
    214.     // Для сравнения имени его нужно прочитать, для этого нужно знать размер
    215.     int size = lstrlenA(name) + 1;
    216.     std::auto_ptr<char> candidate(new char[size]);
    217.  
    218.     // Перебираем имена в массиве имён функций
    219.     for (DWORD index = 0; index < count; ++index)
    220.     {
    221.         DWORD nameRVA;
    222.  
    223.         // Читаем адрес начала строки
    224.         if (!::ReadProcessMemory(
    225.                 hProcess,
    226.                 baseAddress + AddressOfNames + index * sizeof(DWORD),
    227.                 &nameRVA,
    228.                 sizeof(nameRVA),
    229.                 0))
    230.         {
    231.             return HRESULT_FROM_WIN32(::GetLastError());
    232.         }
    233.            
    234.         // Читаем строку
    235.         if (!::ReadProcessMemory(
    236.                 hProcess,
    237.                 baseAddress + nameRVA,
    238.                 candidate.get(),
    239.                 size,
    240.                 0))
    241.         {
    242.             return HRESULT_FROM_WIN32(::GetLastError());
    243.         }
    244.        
    245.         if (strcmp(name, candidate.get()) == 0)
    246.         {
    247.             // Она! Сваливаем :)
    248.             *pnIndex = index;
    249.             return S_OK;
    250.         }
    251.     }
    252.  
    253.     // Такой функции нет
    254.     return E_NOTFOUND;
    255. }
     
  11. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    Создавать потоки можно откуда угодно. Но вот запустить их откуда попало нельзя. Тред войдёт в загрузчик и будет ждать на LdrpLoaderLock и других кс. Да и вообще стартап контекст не доступен, пока тред находится в загрузчике.
     
  12. float

    float New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    113
    спасибо, все же решил с помощью костыля) в одном из перехватов создаю поток.
     
  13. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    float
    Зачем костыли. Решение зависит от того, что будет делать ваш поток. Если не дать ему войти в загрузчик, то он будет работать http://kitrap08.blogspot.com/2011/05/apc-dispatchera.html
    Если какойто тред находится в загрузчике, то стартап контекст лежит в конце SFC: http://www.wasm.ru/forum/viewtopic.php?id=38284
    При использовании HWB нужно отслеживать создаваемые треды через какой либо нотификатор или иной механизм.