基于WH_JOURNALRECORD的键盘钩子

今天学了日志记录钩子,记点笔记

日志记录钩子的特殊性在于虽然是全局钩子,却可以不用写在DLL文件中,罗云彬的书对此进行了猜测,认为这个钩子监控比较底层的硬件事件,HookProc的调用源自于windows内部而非其他进程的地址空间,所以不存在地址空间隔离问题。

.386
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib
IDD_DLG1    equ    1000
IDC_EDT1    equ    1001
.data
.data?
hInstance    dd    ?
hWinMain    dd    ?
hHook        dd    ?
szAscii        db    32 dup (?)
.const
.code
HookProc proc dwCode,wParam,lParam
LOCAL @szKeyState[256]:byte

invoke CallNextHookEx,hHook,dwCode,wParam,lParam
pushad
.if dwCode==HC_ACTION
mov ebx,lParam
assume ebx:ptr EVENTMSG
.if [ebx].message==WM_KEYDOWN

invoke GetKeyboardState,addr @szKeyState
invoke GetKeyState,VK_SHIFT
mov @szKeyState+VK_SHIFT,al
mov ecx,[ebx].paramH
shr ecx,16
invoke ToAscii,[ebx].paramL,ecx,addr @szKeyState,addr szAscii,0
mov byte ptr szAscii[eax],0
.if szAscii==0dh
mov word ptr szAscii+1,0ah
.endif
invoke SendDlgItemMessage,hWinMain,IDC_EDT1,EM_REPLACESEL,FALSE,addr szAscii

.endif
.endif
assume ebx:nothing

popad
ret
HookProc endp
ProcDlgMain proc uses ebx esi edi hWnd,uMsg,wParam,lParam
mov eax,uMsg
.if eax==WM_CLOSE
invoke UnhookWindowsHookEx,hHook
invoke EndDialog,hWnd,0
.elseif eax==WM_INITDIALOG
push hWnd
pop hWinMain
invoke SetWindowsHookEx,WH_JOURNALRECORD,offset HookProc,hInstance,0
.if eax
mov hHook,eax
.else
invoke EndDialog,hWnd,NULL
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret

ProcDlgMain endp
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,eax,IDD_DLG1,0,offset ProcDlgMain,0
invoke ExitProcess,0
end start

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

钩子回调函数的参数:

dwCode:

HC_ACTION:系统准备从消息队列中移去一条消息,消息的具体信息由lParam参数指定的EVENTMSG结构定义

HC_SYSMODALOFF:某个系统模态对话框准备被关闭。

HC_SYSMODALON:某个系统模态对话框准备被建立。

lParam:当dwCode为HC_ACTION时,lParam指向一个EVENTMSG结构。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

EVENTMSG结构如下:

EVENTMSG STRUCT

message     DWORD        ?        ;消息ID

paramL       DWORD        ?        ;wParam

paramH       DWORD        ?        ;lParam

time             DWORD        ?        :消息发生的时间

hwnd            DWORD       ?        :消息对应的窗口句柄

EVENTMSG ENDS

一个有问题的键盘hook

昨天写了一个键盘钩子,,不知道为什么总是无法写入到指定文件,经过测试发现ToAscii后eax总是为0,郁闷ing。。。

代码如下:

.386
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib
.data
hInstance    dd    ?
.data?
hHook    dd    ?
hFile    dd    ?
szAscii        db    4 dup (?)
lpNumWritten    dd    ?
.const
szFileName    db    ’1.txt’,0
.code
DllEntry proc _hInstance,_dwReason,_dwReserved

push _hInstance
pop hInstance
mov eax,_dwReason
.if eax==DLL_PROCESS_ATTACH
invoke CreateFile,offset szFileName,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,0
.if eax
mov hFile,eax
mov eax,TRUE
ret
.endif
.elseif eax==DLL_PROCESS_DETACH
invoke CloseHandle,hFile
mov eax,TRUE
ret
.else
mov eax,TRUE
ret
.endif
ret
DllEntry endp
ProcHook proc _dwCode,_wParam,_lParam
LOCAL @szKeyBoardState[256]:byte
mov eax,_lParam
shr eax,31
.if eax
invoke CallNextHookEx,hHook,_dwCode,_wParam,_lParam
invoke GetKeyboardState,addr @szKeyBoardState
invoke GetKeyState,VK_SHIFT
mov @szKeyBoardState+VK_SHIFT,al
mov ecx,_lParam
shr ecx,16
invoke ToAscii,_wParam,ecx,addr @szKeyBoardState,addr szAscii,0
mov byte ptr szAscii [eax],0
invoke WriteFile,hFile,addr szAscii,sizeof szAscii,offset lpNumWritten,0
.endif
ret

ProcHook endp
InstallHook proc

invoke SetWindowsHookEx,WH_KEYBOARD,offset ProcHook,hInstance,0
mov hHook,eax
ret

InstallHook endp
UninstallHook proc

invoke UnhookWindowsHookEx,hHook
ret

UninstallHook endp
end DllEntry