首页
论坛
课程
招聘
枚举全局钩子
2005-6-19 21:23 23303

枚举全局钩子

2005-6-19 21:23
23303
枚举全局钩子

作者: 一块三毛钱
邮箱: zhongts@163.com
日期: 2005.6.19

    首先强调一点,本文给出的代码只在 WinXP+SP2 下测试通过,使用其他系统的朋友最好看懂代码,然后调试运行。如果不巧系统蓝屏可不要找我哦。:)

    鼠标钩子、键盘钩子等大家一定是耳熟能详,在 Windows 环境下编程的朋友们肯定都和他们打过交道,比如说截获密码什么的都可以用到他们。本文将介绍一种办法可以枚举所有的全局钩子,找到到底是什么动态库创建了钩子(大部分全局钩子都需要通过动态库来实现)。

    下图是程序运行后显示的所有的全局钩子,包括钩子函数在那个动态库中,也就是创建钩子的动态库。图中显示的钩子句柄是指得在当前进程中的句柄,不是系统范围的。比如说 MouseHook 添加了一个全局的鼠标钩子,那么在 explorer 中这个钩子的句柄和在 word 中的句柄是不同的(这一点我是通过 Icesword 观察到的),但都是 MouseHook 添加的钩子都在 mousehook.dll 动态库中。如果想获得 Icesword 一样的结果可以针对每一个进程枚举全局钩子(没试过)。l另外,如果鼠标钩子和键盘钩子不能够显示动态库,可以先动一动鼠标,摁几下键盘再刷新应该就可以显示。



    之所以会写这篇文章是因为在编程板块中有一个主题说判断全局钩子的调用者,所以才想着能不能枚举出所有的全局钩子。但那个主题好像说的是钩子的调用者,又好像全局钩子指得是 Hook API 类型的钩子,没搞懂。在那个主题下 zworm 大侠好像说可以通过一个钩子链的东东来枚举钩子,不过大侠没有细说,我自己也没有在符号文件中找到有关钩子链的符号(我只会这一种办法找系统内部变量,比如活动进程链就可以通过这种办法找到位置),所以准备从 CallNextHookEx 函数慢慢往下追希望能够找到系统是怎么找到下一个钩子函数的。本文介绍的方法就是这样来的(另外有一个很重要的一点会在文章的最后提到)。

invoke  PsGetCurrentThread
mov     ebx, [eax+130h]
mov     _gptiCurrent, ebx
invoke  DbgPrint, $CTA0("ETHREAD:%08X, Win32Thread:%08X\n"), eax, _gptiCurrent

assume  esi : nothing
mov     ebx, -1
.while ebx!=12
        invoke  _PhkFirstValid, _gptiCurrent, ebx
        assume  eax : ptr HOOK
        .while eax
                push    eax     ;_PhkNextValid 的参数
               
                ;根据 win32k.sys 中的 _xxxHkCallHook 得到下面的代码
                mov     edx, [eax].ihmod
                cmp     edx, -1
                jz      @F
                mov     esi, _gptiCurrent       ;esi -> ThreadInfo
                mov     esi, [esi+2Ch]          ;esi -> ProcessInfo
                mov     edx, [esi+edx*4+0A8h]   ;edx = [esi].ahmodLibLoaded[ihmod]
                @@:
               
                ;-------------------------------------
                m2m     [edi].Handle, [eax].hmodule
                m2m     [edi].FuncOffset, [eax].offPfn
                mov     [edi].FuncBaseAddr, edx
                m2m     [edi].iHook, [eax].iHook
                ;-------------------------------------
               
                invoke  DbgPrint, $CTA0("Handle:%08X    FuncOffset:%08X    FuncBaseAddr:%08X    iHook:%d    ihmod:%d\n"), \
                                [eax].hmodule, [eax].offPfn, edx, [eax].iHook, [eax].ihmod
               
                call    _PhkNextValid
                add     dwBytesReturned, sizeof HOOK_INFO
                add     edi, sizeof HOOK_INFO
        .endw
        inc     ebx
.endw

    上面给出的就是核心代码,先找到线程的 Win32Thread 结构,通过这个结构就可以调用 win32k.sys 的内部函数 _PhkFirstValid 找到第一个钩子函数。然后再通过 _PhkNextValid 函数枚举所有的钩子函数。因为每个系统中这两个函数的地址不同,所以我把反汇编后的代码直接提取出来使用。这样可以避免因为系统不同的原因而出错。不过我只在 WinXP+SP2 下运行过,没有在其他的系统下测试,如果大家不能正确运行只好自己修改源代码啦。

    _PhkFirstValid 函数接收两个参数,第一个是 Win32Thread 结构的地址,第二个是要枚举的钩子的类型,比如鼠标钩子。函数返回 HOOK 结构的地址。

HOOK struct
        hmodule         dd  ?
        _Z_             dd  4 dup (?)
        phkNext         dd  ?           ;14h
        iHook           dd  ?           ;18h
        offPfn          dd  ?           ;1Ch
        flags           dd  ?           ;20h
        ihmod           dd  ?           ;24h
        ptiHooked       dd  ?
        rpdesk          dd  ?
HOOK ends

    hmodule 是钩子的句柄,
    _Z_ 这几个不知道是干什么的,
    phkNext 指向下一个 HOOK 结构,
    iHook 钩子类型,
    offPfn 钩子函数的地址,一般都是相对钩子模块的基地址的偏移值,
    flags 一些钩子的属性,比如说钩子是不是已经被销毁,
    ihmod 不太清楚,好像是模块索引。

    _PhkNextValid 函数通过当前钩子函数的 HOOK 结构找到下一个钩子函数的 HOOK 结构。

    找到了钩子函数的 HOOK 结构后,再通过 ihmod 成员找到钩子模块的基地址。这一部分可以参考 _xxxHkCallHook 函数的代码。然后把这些信息返回给 ring3 下的程序显示出来。

    本文给出的代码和结构很大一部分来之于大家手上都可能有的“那份”代码。:)

附件:EnumHook.rar

[招生]科锐逆向工程师培训46期预科班将于 2023年02月09日 正式开班

收藏
点赞0
打赏
分享
最新回复 (24)
雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hyzhang 活跃值 2005-6-19 21:29
2
0
还没细看,先顶一下。
雪    币: 1613
活跃值: 活跃值 (38)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 活跃值 25 2005-6-19 21:33
3
0
太好了
感动ing
好好学习一下
雪    币: 202
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小小鸟 活跃值 2005-6-20 01:45
4
0
win200ads。。蓝了。。
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
q3 watcher 活跃值 2005-6-20 06:28
5
0
强啊,多谢了
雪    币: 137
活跃值: 活跃值 (21)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
shuair 活跃值 2 2005-6-20 08:50
6
0
一块三毛钱
一块三毛钱
查看公开的个人资料
给一块三毛钱发送Email
查找一块三毛钱更多帖子
列出一块三毛钱的精华帖  

初级会员

资 料:
注册日期: Jun 2004
来自:
帖子: 6
精华: 5

高人~.轻易不出手,出手必精华..汗
支持
雪    币: 454
活跃值: 活跃值 (27)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
prince 活跃值 16 2005-6-20 08:57
7
0
高人!
雪    币: 106
活跃值: 活跃值 (373)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
nbw 活跃值 24 2005-6-20 08:58
8
0
先下,回头慢慢学习
雪    币: 114
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
lnn1123 活跃值 13 2005-6-20 10:15
9
0
高手,学习啊
雪    币: 219
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
guoke 活跃值 2005-6-20 13:00
10
0
最初由 一块三毛钱 发布
枚举全局钩子

作者: 一块三毛钱
邮箱: zhongts@163.com
日期: 2005.6.19
........


不错,可惜的是不同系统差别太大,那个内部函数只能在
Xp sp2上用。
雪    币: 219
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
guoke 活跃值 2005-6-20 13:53
11
0
最初由 一块三毛钱 发布
枚举全局钩子

作者: 一块三毛钱
邮箱: zhongts@163.com
日期: 2005.6.19
........


IceSword包含局部钩子,该怎么改这个代码也列出来?
看起来它不是用这个方法。
雪    币: 200
活跃值: 活跃值 (16)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
一块三毛钱 活跃值 11 2005-6-20 20:54
12
0
不好意思,把 zmworm 大侠的名字写错了。
雪    币: 200
活跃值: 活跃值 (16)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
一块三毛钱 活跃值 11 2005-6-20 20:56
13
0
最初由 guoke 发布


不错,可惜的是不同系统差别太大,那个内部函数只能在
Xp sp2上用。


2000 系统上应该是有的,你可以带符号文件反汇编一下 win32k.sys 看看有没有这两个内部函数。
雪    币: 200
活跃值: 活跃值 (16)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
一块三毛钱 活跃值 11 2005-6-20 21:10
14
0
最初由 guoke 发布


IceSword包含局部钩子,该怎么改这个代码也列出来?
看起来它不是用这个方法。


我在文章中枚举的钩子应该包括本线程的局部钩子,不单是全局钩子。你可以把 sys 源代码中的 PsGetCurrentThread 函数去掉,改成从 ring3 程序中传入给定的线程试一试。看看能不能枚举出所有的局部钩子和全局钩子。
雪    币: 100
活跃值: 活跃值 (19)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
runjin 活跃值 4 2005-6-21 13:10
15
0
昨晚正在备份论坛数据库,去了大半的时候,运行这个东西,马上重新启动,汗
雪    币: 1141
能力值: (RANK:460 )
在线值:
发帖
回帖
粉丝
monkeycz 活跃值 11 2005-6-22 10:34
16
0
最初由 一块三毛钱 发布
本文给出的代码和结构很大一部分来之于大家手上都可能有的“那份”代码。:)

雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Xfreeboy 活跃值 2005-6-23 18:36
17
0
顶!!
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wrdwtwjj 活跃值 2005-7-30 15:29
18
0
看了一下phkfirstvalid,这个函数流程是:
取本地线程钩子;
若为空,取全局钩子;
测试取到的钩子;
返回第一个有效的;

换言之,若有本地钩子的话,可能取不到全局钩子。
另外还有一个函数phkglobalfirstvalid,没有第一步。

我的系统是2000sp4,phkfirstvalid的代码和一块三毛钱给出的看来是一样的,但程序运行死机,不知问题在哪里。

才刚刚开始看windows,说错了不要笑哈。。。
雪    币: 19
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
pendan2001 活跃值 4 2005-7-30 16:32
19
0
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
987654321 活跃值 2005-7-31 12:08
20
0
向高人学习一下
雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Xfreeboy 活跃值 2005-7-31 13:09
21
0
在2000和2003下运行都会死机,郁闷啊
雪    币: 193
活跃值: 活跃值 (13)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
林海雪原 活跃值 6 2005-7-31 13:16
22
0
顶!学习!学习!
雪    币: 151
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:1010 )
在线值:
发帖
回帖
粉丝
liyangsj 活跃值 25 2005-8-1 08:53
23
0
厉害啊,先下了!
雪    币: 244
活跃值: 活跃值 (85)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sunson 活跃值 2005-8-1 13:20
24
0
看不懂,还是支持一下!
雪    币: 205
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
starluck 活跃值 1 2005-8-1 17:45
25
0
2000下不行啊,运行后系统立即不稳定了。晕死
游客
登录 | 注册 方可回帖
返回