Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Отлов событий другого приложения через хуки


Автор: MANAB 15.11.2010, 03:29
Хочу сделать так, чтобы моя программа могла отловить факт нажатий кнопок другой конкретной уже запущенной программы.

Делаю длл, в ней вызываю функцию, которая находит окно нужной мне программы, получает ее ThreadId и ставит хук:

Код

void Init( )
{
    USES_CONVERSION;

    //find PokerStars window
    WCHAR wWindowName[256];
    size_t pos = 0;

    HWND hWndF = GetTopWindow( NULL );
    GetWindowText( hWndF, wWindowName, 256 );
    if ( ( pos = string( W2A( wWindowName ) ).find( "MyTestProgram" ) ) == string::npos )
    {
        while ( hWndF != NULL )
        {
            hWndF = GetNextWindow( hWndF, GW_HWNDNEXT );
            GetWindowText( hWndF, wWindowName, 256 );
            if ( ( pos = string( W2A( wWindowName ) ).find( "MyTestProgram" ) ) != string::npos )
                break;
        }
    }

    g_hPokerMainWnd = hWndF;

    //get process id
    DWORD dwThreadID;
    DWORD dwProcessID;
    dwThreadID = GetWindowThreadProcessId( g_hPokerMainWnd, &dwProcessID );

    //create hook
    g_hhook = SetWindowsHookEx( WH_MSGFILTER, &HookProc, (HINSTANCE)g_hMod, dwThreadID );
}


Проверял g_hhook - не NULL.

Обработчик
Код

LRESULT CALLBACK HookProc( int nCode, WPARAM wParam, LPARAM lParam )
{
    MessageBox( NULL, L"", L"", MB_OK );

    return CallNextHookEx( g_hhook, nCode, wParam, lParam );
}

эмоций никаких не проявил.
Как я ни извращался, какие idHook ни ставил - молчит как партизан.  smile 

Где я ступил? smile 

Автор: ASMatic 15.11.2010, 04:18
видимо не задумывались - PokerStars вполне возможно защиту сделала от таких как выsmile
попробуйте свой код натравить на блокнот...

если действительно защита, скорей всего от хуков - тогда вам надо будет подгрузить длл в покерстарз и там уже сабклассить ихнее окно.
я бы так изначально делал, темболее если на локальном компе - AppInitDlls неплохо помогает вместе с проверкой в дллмеин имени процесса.

Автор: MANAB 15.11.2010, 11:07
Я тоже сначала так подумал, но перед тем как создать тему быстренько создал форму с парой кнопочек и обработчиками для них, чтобы проверить. Тоже не отлавливает. smile 

Автор: bass 15.11.2010, 11:31
надеюсь весь код который ты предоставил находиться в длл.......
После установки хука глянь процесс-експлорером или отладчиком в процессе присутствует длл??????
А вообще насколько помню в хук надо хандл процесса кидать .........
Посмотри функцию опенпроцес(на английском).
 dwThreadID = GetWindowThreadProcessId( g_hPokerMainWnd, &dwProcessID );
Далее опен процесс с флагом для всего и вот это dwProcessID..... и хандл в хук.....

Добавлено через 1 минуту и 45 секунд
Да и что ты мучаешься перебирая все окна findwindow на что тебе.....

Автор: GremlinProg 15.11.2010, 11:41
Цитата(bass @  15.11.2010,  13:31 Найти цитируемый пост)
А вообще насколько помню в хук надо хандл процесса кидать .........Посмотри функцию опенпроцес(на английском).

нет - идентификатор потока:
Цитата(SetWindowsHookEx Function @  MSDN)

dwThreadId
[in] Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread. 

g_hMod - HMODULE загруженной библиотеки?
Цитата(SetWindowsHookEx Function @  MSDN)

hMod
[in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. 

Автор: bass 15.11.2010, 11:47
Цитата(GremlinProg @ 15.11.2010,  11:41)
Цитата(bass @  15.11.2010,  13:31 Найти цитируемый пост)
А вообще насколько помню в хук надо хандл процесса кидать .........Посмотри функцию опенпроцес(на английском).

нет - идентификатор потока:
Цитата(SetWindowsHookEx Function @  MSDN)

dwThreadId
[in] Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread. 

g_hMod - HMODULE загруженной библиотеки?
Цитата(SetWindowsHookEx Function @  MSDN)

hMod
[in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. 

Приношу извинения я еще не выспался....

Автор: MANAB 15.11.2010, 12:27
g_hMod - да, это хендл загруженной библиотеки:
Код

HANDLE g_hMod;
HHOOK g_hhook;



BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
    g_hMod = hModule;

    return TRUE;
}

И да, весь код находится внутри Dll, я просто вызываю в своей программе одну функцию Init, которая все это счастье запускает.

Автор: GremlinProg 15.11.2010, 12:32
а если сменить тип хука, например на WH_GETMESSAGE?

Автор: MANAB 15.11.2010, 12:39
Цитата(bass @  15.11.2010,  11:31 Найти цитируемый пост)
После установки хука глянь процесс-експлорером или отладчиком в процессе присутствует длл??????

Проверил, присутствует.

Добавлено через 1 минуту и 56 секунд
Цитата(GremlinProg @  15.11.2010,  12:32 Найти цитируемый пост)
а если сменить тип хука, например на WH_GETMESSAGE? 

Вообще все idHook проверил, ничего.

Добавлено через 7 минут и 42 секунды
Поставил глобальный хук (без dwThreadID) - вроде реагирует. Вроде - потому что скажем для мышки - не все нажатия почему-то перехватываются...
Попробую на другом компе с XP, может это все из-за того, что у меня Windows 7 64-битная.

Автор: MANAB 15.11.2010, 13:10
Хм... Там тоже самое.
Что странно, глобальный хук вроде ставлю на клавиатуру:
Код

g_hhook = SetWindowsHookEx( WH_KEYBOARD, &HookProc, (HINSTANCE)g_hMod, 0 );


а нажатия клавиш не отлавливаются  smile 

Автор: GremlinProg 15.11.2010, 13:17
Цитата(MANAB @  15.11.2010,  14:39 Найти цитируемый пост)
64-битная

а хук 32-х, или приложение 32-х, а хук 64-х?

вобщем битность у приемника и перхватчика должна совпадать, у нас уже была дискуссия на эту тему

Добавлено через 5 минут и 8 секунд
Цитата(SetWindowsHookEx Function @  MSDN)

SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names. 

Автор: MANAB 15.11.2010, 13:27
И хук и приложение 32х битные. На Windows XP тоже самое все, проверял.

Автор: bass 15.11.2010, 20:43
Странооо ........  Воббще должно может не тот HWND находить поставь логирование......... 
И попробуй findwindow......
Вообще я использую замену Windowproc ..... Injekt.... Если что кодом могу помоч.....

Добавлено @ 20:45
WH_KEYBOARD Может работать в своем процессе.............

Автор: MANAB 15.11.2010, 23:09
bass, если можешь помочь с инъекцией - буду очень признателен. Я читал про нее, но еще не разобрался. Знаю только что там 3 способа есть, и один из них через хуки.

Автор: bass 16.11.2010, 22:11
Лови рабочий проект на билдоре.......
унит1 сам исходный текст Требуемая библиотека псапи.... Если что либу для билдора могу кинуть......
Смотри у меня инжект вызывает еще и функцию... Сначало енжектит потом идет вызов функции и выход из потока если он вернеться.......
Без функции процес рухнет........ проджект 1 готовый ехе но может библиотек нехватить не помню как компилятор выставил(Если что  кину)....
И если будешь на студии компелить поставь однобайтовое выравнивание иначе процес жертва ружиться....
Вопросы возниктнут звони -))))))

Добавлено через 8 минут и 49 секунд
Способов больше .......
Вот какие я знаю.......
1. как я скинул через кретеремотетшреад.
2. через реестр только длл погрузиться во все процессы где есть библиотека усер32.
3ю через хуки.
4ю написание подложки со всеми экспортируемыми функциями,  и переименование длл.
5ю изменение кода родной длл чтоб подгружалась твоя даже проги спец есть(встречал щас не вспомню как назваються)... Но я делаю через отладчик...

Раньше через сенд мессге можно было но сеЙчас лавочку прикрыли..... с вм_таймер ......
 smile  Так что както так .....
В винлогон тоже через реестр можно попасть.....
А чтоб подменить винпрок используй setwindowlong насколько помню......
С уважением Игорь.
  

Автор: MANAB 18.11.2010, 01:06
bass, спасибо, буду ковырять.



Да, и я разобрался, почему сообщения не отлавливались. Надо было запускать программу с правами администратора smile 
Работать-то работает, а вот брейками теперь не попользуешься(

Интересно, есть ли возможность их программно установить при запуске программы?

Автор: bass 18.11.2010, 03:54
Не понял чем там у тебя не получается пользоваться.....
Но насколько я понял тебе нежно узнать запускается сторонние приложение или нет?????
Если перехватывать запуск процесса на ранней стадии..... То писать драйвер....
А так периодически переберать имена процессов ....
Код

  DWORD GetProcessIdByName(char* lpProcessName)
{
   // Get the list of process identifiers.

   DWORD aProcesses[1024], cbNeeded, cProcesses;
   unsigned int i;

   if (!EnumProcesses (aProcesses, sizeof(aProcesses), &cbNeeded ))
 return 0;

   // Calculate how many process identifiers were returned.

   cProcesses = cbNeeded / sizeof(DWORD);


   char szProcessName[MAX_PATH] = "unknown";
   for (i = 0; i < cProcesses; i++)
   {
 HANDLE hProcess = OpenProcess (PROCESS_QUERY_INFORMATION |
 PROCESS_VM_READ,
 FALSE, aProcesses[i]);

 // Get the process name.

 if ( hProcess )
 {
   HMODULE hMod;
   DWORD cbNeeded;

   if ( EnumProcessModules (hProcess, &hMod, sizeof(hMod),
   &cbNeeded) )
   {
   GetModuleBaseName (hProcess, hMod, szProcessName,
       sizeof(szProcessName));
   }
 }

 // Print the process name and identifier.
 if(!lstrcmpi (szProcessName, lpProcessName))
 {
   CloseHandle (hProcess);
   return aProcesses[i];
 }

 CloseHandle (hProcess);
   }
   return NULL;
}



инклуде псапи....

Автор: MANAB 18.11.2010, 11:41
Нет  smile 
Я хочу отследить нажатие определенной кнопки определенного окна. Поставил хук, который это делает (как уже писал выше, запускать экзешник, который подгружает хук из длл, нужно с правами администратора, именно поэтому у меня не работало). Неудобство заключается лишь с в том, что в теперь в вижуал студии брейкпоинты на хуках не поставишь, чтобы это дело отладить, посмотреть где там и чего(

Автор: bass 18.11.2010, 14:14
Я олькой пользуюсь......
Бреками редко....
А вообще это все в контексте другова процесса происходит........
Щас сам мучаюсь с хуками и подменой винпрок.....


Автор: xvr 18.11.2010, 15:10
Цитата(MANAB @  18.11.2010,  11:41 Найти цитируемый пост)
Неудобство заключается лишь с в том, что в теперь в вижуал студии брейкпоинты на хуках не поставишь,
Почему это не поставишь? Делаешь проект из твоей dll, в пропертях отладки прописываешь в поле 'Исполняемый файл' приложение, в котором собираешься ставить хуки. Ставишь break'и, какие нужно. Запускаешь на исполнение (F5). Потом снаружи запускаешь свою основную программу (можно из другой копии VS).


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)