windows消息钩子很古老,但目前仍有很多地方需要用到,简单跟踪了一下函数执行流程,函数用法如下(MSDN):
函数功能:该函数将一个应用程序定义的挂钩处理过程安装到挂钩链中去,您可以通过安装挂钩处理过程来对系统的某些类型事件进行监控,这些事件与某个特定的线程或系统中的所有事件相关.
函数原形:
HHOOK SetWindowsHookEx(int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId);
HHOOK SetWindowsHookEx(int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId
);
.text:77D31211 ; HHOOK __stdcall SetWindowsHookExA(int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId)
.text:77D31211 public _SetWindowsHookExA@16
.text:77D31211 _SetWindowsHookExA@16 proc near ; DATA XREF: .text:off_77D13928.o
.text:77D31211
.text:77D31211 idHook = dword ptr 8
.text:77D31211 lpfn = dword ptr 0Ch
.text:77D31211 hModule = dword ptr 10h
.text:77D31211 dwThreadId = dword ptr 14h
.text:77D31211
.text:77D31211 mov edi, edi
.text:77D31213 push ebp
.text:77D31214 mov ebp, esp
.text:77D31216 push 2 ;DWORD dwFlags
.text:77D31218 push [ebp+dwThreadId]
.text:77D3121B push [ebp+hModule]
.text:77D3121E push [ebp+lpfn]
.text:77D31221 push [ebp+idHook]
.text:77D31224 call _SetWindowsHookExAW@20 ; SetWindowsHookExAW(x,x,x,x,x)
.text:77D31229 pop ebp
.text:77D3122A retn 10h
.text:77D3122A _SetWindowsHookExA@16 endp
HHOOK __stdcall SetWindowsHookExAW(int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId,DWORD dwFlags
.text:77D28157 ; int __stdcall SetWindowsHookExAW(int idHook, int lpfn, HMODULE hModule, int dwThreadId, DWORD dwFlags
.text:77D28157 _SetWindowsHookExAW@20 proc near ; CODE XREF: SetWindowsHookExW(x,x,x,x)+13.p
.text:77D28157 ; SetWindowsHookExA(x,x,x,x)+13.p
.text:77D28157
.text:77D28157 Filename = word ptr -20Ch
.text:77D28157 var_4 = dword ptr -4
.text:77D28157 idHook = dword ptr 8
.text:77D28157 lpfn = dword ptr 0Ch
.text:77D28157 hModule = dword ptr 10h
.text:77D28157 dwThreadId = dword ptr 14h
.text:77D28157 Mod = dword ptr 18h
.text:77D28157
.text:77D28157 mov edi, edi
.text:77D28159 push ebp
.text:77D2815A mov ebp, esp
.text:77D2815C sub esp, 20Ch ; 为局部变量分配内存空间0x20Ch = 524字节,此为双字节数组,共261个元素,所以最大元素下标是260[MAX_PATH]
.text:77D28162 mov eax, ___security_cookie
.text:77D28167 push esi ; 保存esi
.text:77D28168 mov esi, [ebp+hModule]
.text:77D2816B test esi, esi
.text:77D2816D push edi
.text:77D2816E mov edi, [ebp+lpfn]
.text:77D28171 mov [ebp+var_4], eax
.text:77D28174 jz short loc_77D2818D ; hmod为NULL
.text:77D28176 push 104h ; nSize
.text:77D2817B lea eax, [ebp+Filename]
.text:77D28181 push eax ; lpFilename
.text:77D28182 push esi ; hModule
.text:77D28183 call ds:__imp__GetModuleFileNameW@12 ; GetModuleFileNameW(x,x,x)
.text:77D28189 test eax, eax
.text:77D2818B jz short loc_77D281AC ; 获取模块句柄失败
.text:77D2818D
.text:77D2818D loc_77D2818D: ; CODE XREF: SetWindowsHookExAW(x,x,x,x,x)+1D.j
.text:77D2818D push [ebp+dwFlags]
.text:77D28190 mov eax, esi ;esi也拥有模块句柄
.text:77D28192 push edi ;lpfn入栈
.text:77D28193 push [ebp+idHook]
.text:77D28196 neg eax ;取反操作,如果eax为NULL的话,CF位为0,否则CF置1
.text:77D28198 push [ebp+dwThreadId]
.text:77D2819B sbb eax, eax ;若CF为0,eax = 0,否则eax为-1
.text:77D2819D lea ecx, [ebp+Filename]
.text:77D281A3 and eax, ecx ;sbb后,若eax为0,则结果为0,否则为ecx
.text:77D281A5 push eax ;判断结果
.text:77D281A6 push esi ;esi拥有模块句柄
.text:77D281A7 call __SetWindowsHookEx@24 ; _SetWindowsHookEx(x,x,x,x,x,x)
.text:77D281AC
.text:77D281AC loc_77D281AC: ; CODE XREF: SetWindowsHookExAW(x,x,x,x,x)+34.j
.text:77D281AC mov ecx, [ebp+var_4]
.text:77D281AF pop edi
.text:77D281B0 pop esi
.text:77D281B1 call @__security_check_cookie@4 ; __security_check_cookie(x)
.text:77D281B6 leave
.text:77D281B7 retn 14h
.text:77D281B7 _SetWindowsHookExAW@20 endp
HHOOK __stdcall SetWindowsHookExAW(int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId,DWORD dwFlags)
{
WCHAR Filename[MAX_PATH];
if (hmod != NULL)
{
//获取文件名
if (!GetModuleFileNameW(hmod,Filename,MAX_PATH))
{
//该参数虽然存在,但经验证是伪造的,返回NULL
return NULL;
}
}
return _SetWindowsHookEx(hmod,(hmod == NULL) ? NULL:Filename,dwThreadId,idHook,lpfn,dwFlags);
}
.text:77D281BF ; int __stdcall _SetWindowsHookEx(HMODULE hmod, LPCWSTR Filename, DWORD dwThreadId, int idHook, HOOKPROC lpfn, DWORD dwFlags)
.text:77D281BF __SetWindowsHookEx@24 proc near ; CODE XREF: SetWindowsHookExAW(x,x,x,x,x)+50.p
.text:77D281BF
.text:77D281BF usFileName = byte ptr -10h
.text:77D281BF usModuleName = dword ptr -8
.text:77D281BF var_4 = dword ptr -4
.text:77D281BF hmod = dword ptr 8
.text:77D281BF Filename = dword ptr 0Ch
.text:77D281BF dwThreadId = dword ptr 10h
.text:77D281BF idHook = dword ptr 14h
.text:77D281BF lpfn = dword ptr 18h
.text:77D281BF Flags = dword ptr 1Ch
.text:77D281BF
.text:77D281BF mov edi, edi
.text:77D281C1 push ebp
.text:77D281C2 mov ebp, esp
.text:77D281C4 sub esp, 10h ; 分配16字节大小堆栈空间
.text:77D281C7 push [ebp+Filename] ; Filename入栈
.text:77D281CA and [ebp+var_4], 0 ;
.text:77D281CE lea eax, [ebp+usFileName]
.text:77D281D1 push eax
.text:77D281D2 mov [ebp+usModuleName], eax
.text:77D281D5 call ds:__imp__RtlInitUnicodeString@8 ; RtlInitUnicodeString(x,x)
.text:77D281DB push [ebp+dwFlags]
.text:77D281DE push [ebp+lpfn]
.text:77D281E1 push [ebp+idHook]
.text:77D281E4 push [ebp+dwThreadId]
.text:77D281E7 push [ebp+usModuleName]
.text:77D281EA push [ebp+hmod]
.text:77D281ED call _NtUserSetWindowsHookEx@24 ; NtUserSetWindowsHookEx(x,x,x,x,x,x)
.text:77D281F2 leave
.text:77D281F3 retn 18h
.text:77D281F3 __SetWindowsHookEx@24 endp
HHOOK __stdcall _SetWindowsHookEx(HMODULE hmod,LPCWSTR Filename,DWORD dwThreadId,int idHook,HOOKPROC lpfn,DWORD dwFlags)
{
UNICODE_STRING usFileName;
//初始化UNICODE字符串结构
RtlInitUnicodeString(&usFileName,Filename);
return NtUserSetWindowsHookEx(hmod,&usFileName,dwThreadId,idHook,lpfn,dwFlags);
}
.text:77D281FB ; __stdcall NtUserSetWindowsHookEx(x, x, x, x, x, x)
.text:77D281FB _NtUserSetWindowsHookEx@24 proc near ; CODE XREF: _SetWindowsHookEx(x,x,x,x,x,x)+2E.p
.text:77D281FB mov eax, 1225h
.text:77D28200 mov edx, 7FFE0300h
.text:77D28205 call dword ptr [edx]
.text:77D28207 retn 18h
.text:77D28207 _NtUserSetWindowsHookEx@24 endp
HHOOK
NTAPI
NtUserSetWindowsHookEx(
HINSTANCE Mod,
PUNICODE_STRING ModuleName,
DWORD ThreadId,
int HookId,
HOOKPROC HookProc,
DWORD dwFlags);
.text:BF85EA67 ; START OF FUNCTION CHUNK FOR _NtUserSetWindowsHookEx@24
.text:BF85EA67
.text:BF85EA67 loc_BF85EA67: ; CODE XREF: NtUserSetWindowsHookEx(x,x,x,x,x,x)+1C.j
.text:BF85EA67 push 57h ; 错误码:87 ,参数不正确
.text:BF85EA69 call _UserSetLastError@4 ; UserSetLastError(x)
.text:BF85EA6E jmp short loc_BF85EAAE ; 准备退出
.text:BF85EA6E ; END OF FUNCTION CHUNK FOR _NtUserSetWindowsHookEx@24
.text:BF85EA75 ; int __stdcall NtUserSetWindowsHookEx(HINSTANCE Mod, PUNICODE_STRING ModuleName, DWORD ThreadId, int HookId, HOOKPROC HookProc, BOOL Ansi)
.text:BF85EA75 _NtUserSetWindowsHookEx@24 proc near ; DATA XREF: .data:BF99E094.o
.text:BF85EA75
.text:BF85EA75 Mod = dword ptr 8
.text:BF85EA75 ModuleName = dword ptr 0Ch
.text:BF85EA75 ThreadId = dword ptr 10h
.text:BF85EA75 HookId = dword ptr 14h
.text:BF85EA75 HookProc = dword ptr 18h
.text:BF85EA75 Ansi = dword ptr 1Ch
.text:BF85EA75
.text:BF85EA75 ; FUNCTION CHUNK AT .text:BF85EA67 SIZE 00000009 BYTES
.text:BF85EA75
.text:BF85EA75 mov edi, edi
.text:BF85EA77 push ebp
.text:BF85EA78 mov ebp, esp
.text:BF85EA7A push esi
.text:BF85EA7B call _EnterCrit@0 ; EnterCrit()
.text:BF85EA80 xor esi, esi
.text:BF85EA82 cmp [ebp+ThreadId], esi
.text:BF85EA85 jz short loc_BF85EABA ; 进程ID为0,说明是系统全局消息钩子
.text:BF85EA87 push [ebp+ThreadId]
.text:BF85EA8A call _PtiFromThreadId@4 ; 通过线程ID获取PTHREADINFO指针
.text:BF85EA8F cmp eax, esi
.text:BF85EA91 jz short loc_BF85EA67 ; 没有获取
.text:BF85EA93
.text:BF85EA93 loc_BF85EA93: ; CODE XREF: NtUserSetWindowsHookEx(x,x,x,x,x,x)+47.j
.text:BF85EA93 push [ebp+dwFlags]
.text:BF85EA96 push [ebp+HookProc]
.text:BF85EA99 push [ebp+HookId]
.text:BF85EA9C push eax
.text:BF85EA9D push [ebp+ModuleName]
.text:BF85EAA0 push [ebp+Mod]
.text:BF85EAA3 call _zzzSetWindowsHookEx@24 ; zzzSetWindowsHookEx(x,x,x,x,x,x)
.text:BF85EAA8 cmp eax, esi ; 判断结果为NULL
.text:BF85EAAA jz short loc_BF85EAAE ; 失败则跳转
.text:BF85EAAC mov esi, [eax] ; 暂存结果
.text:BF85EAAE
.text:BF85EAAE loc_BF85EAAE: ; CODE XREF: NtUserSetWindowsHookEx(x,x,x,x,x,x)-7.j
.text:BF85EAAE ; NtUserSetWindowsHookEx(x,x,x,x,x,x)+35.j
.text:BF85EAAE call _LeaveCrit@0 ; LeaveCrit()
.text:BF85EAB3 mov eax, esi
.text:BF85EAB5 pop esi
.text:BF85EAB6 pop ebp
.text:BF85EAB7 retn 18h
.text:BF85EABA ; ---------------------------------------------------------------------------
.text:BF85EABA
.text:BF85EABA loc_BF85EABA: ; CODE XREF: NtUserSetWindowsHookEx(x,x,x,x,x,x)+10.j
.text:BF85EABA xor eax, eax
.text:BF85EABC jmp short loc_BF85EA93
.text:BF85EABC _NtUserSetWindowsHookEx@24 endp
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!