WIN32汇编语言教程:第11章 动态链接库和钩子 · 11.2 Windows钩子(2)
NAME = Main DLL = Hookdll ML_FLAG = /c /coff LINK_FLAG = /subsystem:windows DLL_LINK_FLAG = /subsystem:windows /section:.bss,S $(DLL).dll $(NAME).exe: $(DLL).dll: $(DLL).obj $(DLL).def Link $(DLL_LINK_FLAG) /Def:$(DLL).def /Dll $(DLL).obj $(NAME).exe: $(NAME).obj $(NAME).res Link $(LINK_FLAG) $(NAME).obj $(NAME).res .asm.obj: ml $(ML_FLAG) $< .rc.res: rc $< clean: del *.obj del *.res del *.exp del *.lib
HookDll.asm文件的内容如下:
.386 .model flat, stdcall option casemap :none ;#################################################################### ; Include 文件定义 ;#################################################################### include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib ;#################################################################### .data hInstance dd ? .data? hWnd dd ? hHook dd ? dwMessage dd ? szAscii db 4 dup (?) ;#################################################################### .code ;#################################################################### DllEntry proc _hInstance,_dwReason,_dwReserved Push _hInstance pop hInstance mov eax,TRUE ret DllEntry Endp ;#################################################################### ; 键盘钩子回调函数 ;#################################################################### HookProc proc _dwCode,_wParam,_lParam local @szKeyState[256]:byte invoke CallNextHookEx,hHook,_dwCode,_wParam,_lParam invoke GetKeyboardState,addr @szKeyState invoke GetKeyState,VK_SHIFT mov @szKeyState + VK_SHIFT,al mov ecx,_lParam shr ecx,16 invoke ToAscii,_wParam,ecx,addr @szKeyState,addr szAscii,0 mov byte ptr szAscii [eax],0 invoke SendMessage,hWnd,dwMessage,dword ptr szAscii,NULL xor eax,eax ret HookProc endp ;#################################################################### ; 安装钩子 ;#################################################################### InstallHook proc _hWnd,_dwMessage push _hWnd pop hWnd push _dwMessage pop dwMessage invoke SetWindowsHookEx,WH_KEYBOARD,addr HookProc,\ hInstance,NULL mov hHook,eax ret InstallHook endp ;#################################################################### ; 卸载钩子 ;#################################################################### UninstallHook proc invoke UnhookWindowsHookEx,hHook ret UninstallHook endp ;#################################################################### End DllEntry
需要共享的变量被放在 .data?段中,如钩子句柄和钩住的按键内容等,仅dll程序的实例句柄不需要共享,不需要共享的变量放在 .data段中。动态链接库的入口函数例行公事地返回了一个TRUE来表示允许被装入。程序中只写了3个函数,HookProc是钩子回调函数,InstallHook和 UninstallHook函数是供主程序使用的钩子安装函数和卸载函数。这3个函数是需要导出的,所以HookDll.def文件中包括了它们的名称:
EXPORTS HookProc InstallHook UninstallHook
InstallHook子程序用来安装钩子,程序为它设计了两个参数:窗口句柄和自定义消息ID。动态链接库保存这两个参数,以便在钩子回调函数收到消息的时候将截获的按键通过自定义消息ID转发给父窗口,这样父窗口在初始化完成后只需要等待自定义消息ID就可以了。
在子程序中,通过SetWindowsHookEx函数安装钩子。SetWindowsHookEx函数的用法是:
invoke SetWindowsHookEx,idHook,lpHookProc,hInstance,dwThreadID .if eax mov hHook,eax .endif
idHook参数指定钩子的类型,它就是表11.1中列出的钩子名称。例子中要安装的是键盘钩子,所以使用WH_KEYBOARD。lpHookProc参数指出钩子回调函数的地址。
hInstance 指定钩子回调函数所在DLL的实例句柄。如果安装的是局部钩子的话,由于局部钩子的回调函数并不需要放在动态链接库中,这时这个参数就使用NULL。
dwThreadID是安装钩子后想监控的线程的ID号。该参数可以决定钩子是局部的还是系统范围的。如果参数指定的是自己进程中的某个线程ID号,那么该钩子是一个局部钩子;如果指定的线程ID是另一个进程中某个线程的ID,那么安装的钩子是一个局部的远程钩子;如果想要安装系统范围的全局钩子的话,可以将这个参数指定为NULL,这样钩子就会被解释成系统范围的,可以用来监控所有的进程及它们的线程。
上页:第11章 动态链接库和钩子 · 11.2 Windows钩子(1) 下页:第11章 动态链接库和钩子 · 11.2 Windows钩子(3)