2024年6月14日发(作者:)
第26卷第5期
2009年5月
计算机应用与软件
ComputerApplications
andSoftware
VoI.26No.5
May
2009
HOOK
API时代码注入方法和函数重定向技术研究
舒敬荣朱安国齐善明
(解放军炮兵学院二系安微合肥230031)
摘要HOOK
API是一种高级编程技术,在介绍WindowsHOOK技术的基础上,阐述了HOOKAPI技术的概念,分析了HOOK
API技术的实现原理,给出了三种实现HOOKAPI技术时的代码注入方法,即使用钩子注入DLL、使用注册表注入DLL及使用远程
线程注入DLL。探讨两种实现HOOKAPI技术时的函数重定向技术,即利用PE文件中的导入表实现函数的重定向及通过嵌入汇编
代码实现函数的重定向。
关键词HOOK机制HOOKAPI代码注入函数重定向Windows编程
STUDYONCODE
EMBEDDINGMETHoD
TECHNIQUE
WHEN
Shu
Jingrong
ANDFUNCTIoNREDIRECTloN
HooKINGAPI
Zhu
Anguo
Qi
Shanming
(Two
Department,ArtilleryAcademy
ofP上A.,Hefei230031,Anhui。China)
Abstract‘|HOOKAPIiskindof
advanced
programmingtechnique.On
thebasisof
introducing
Windows
HOOK
technique,in
this
paper
it
expounds
the
concept
ofHOOKAPI
technique,analyses
itsrealization
principle,andputs
forwardthreekindsofDLLcode
embedding
meth-
ods
when
realizing
HOOK
API:(1)by
using
hooks;(2)by
usingregistration
table;(3)byusing
remotethread.Italsodiscusses
functionredirection
techniques
when
realizing
HOOK
Keywords
HOOK
two
kindsof
API:(I)by
using
PEfile
importingtable;(2)by
embedding
assemble
language
code.
mechanism
HOOKAPICode
embedding
Functionredirection
Windows
programming
0引
HOOK
言
API是一种高级编程技术,很多问题的实现和解决
1
Windows系统中的HooK(钩子)机制
Windows系统中HoOK机制的概念
Windows系统是建立在消息驱动机制上的,整个系统都是
1.1
都要用到这种技术。这里所说的API,是广义上的API,包括
DOS下的中断、WINDOWS里的API、中断服务、IFS和NDIS过
滤等。比如大家熟悉的即时翻译软件,就是靠HOOK
TextOut()
或ExtTextOut()这两个函数实现的,在操作系统用这两个函数
输出文本之前,就把相应的英文替换成中文而达到即时翻译;
IFS和NDIS过滤也是如此,在读写磁盘和收发数据之前,系统
会调用第三方提供的回调函数来判断操作是否可以放行,它与
普通HOOK不同,它是操作系统允许的,由操作系统提供接口
来安装回调函数。HOOKAPI技术还可用于网络攻击和网络防
御。因为HOOKAPI技术是实现黑客、病毒及反黑客、反病毒软
件的基础。不管是DOS下的病毒或WINDOWS里的病毒,都是
靠HOOK系统服务来实现自己的功能的:DOS下的病毒靠
HOOK
INT
通过消息的传递来实现的。而HOOK(钩子)是Windows系统中
非常重要的系统接口,用它可以截获并处理送给其他应用程序
的消息,然后完成普通应用程序难以实现的功能。钩子可以监
视系统或进程中的各种事件消息,截获发往目标窗口的消息并
进行处理。因此,就可以通过在系统中安装自定义的钩子,监视
系统中特定事件的发生,完成特定的功能,比如截获键盘/鼠标
的输入、屏幕取词、日志监视等。可见,利用钩子可以实现许多
特殊而有用的功能。对于高级编程人员来说,掌握钩子的编程
方法是很有必要的。
关于Windows钩子必须要掌握以下几点:
(1)钩子是用来截获系统中的消息流的。利用钩子,可以
处理任何消息,包括其他进程的消息;
(2)截获消息后,用于处理消息的子程序叫做钩子函数,它
是应用程序自定义的一个函数,在安装钩子时要把这个函数的
地址告诉Windows;
(3)系统中同一时间可能有多个进程安装了钩子,多个钩
收稿13期:2007—12—06。舒敬荣,讲师,主研领域:自动化,指挥自
动化,飞行力学。
21来感染文件(文件型病毒),靠HOOK
INT
13来感
染引导扇区(引导型病毒);WINDOWS下的病毒靠HOOK系统
API,或者安装IFS(CIH病毒所用的方法)来感染文件。
由于涉及到知识产权和商业机密,微软一直不提倡编程者
HOOK它的系统API,而提供IFS和NDIS等其他过滤接口,也是
为了适应杀毒软件和防火墙的需要才开放的。所以在大多数时
候,HOOK
APl要靠自己的编程来完成。
万方数据
108
计算机应用与软件
2009篮
子函数在一起组成钩子链。所以在处理截获到的消息时,应该
把消息事件传递F去,以便其它钩子也有机会处理这一消息。
而且最近安装的钩子放在链的开始,而最早安装的钩子放在最
后,也就是后加入的先获得控制权;
(4)钩子函数有很多类型。按事件类型分类,主要有键盘
钩子、鼠标钩子、外壳钩子、13志钩子和窗口过程钩子等;按使用
范围分类,主要有线程钩子和系统钩子。线程钩子监视指定线
程的事件消息,系统钩子监视系统中的所有线程的事件消息。
因为系统钩子会影响系统中所有的应用程序,所以钩子函数必
须放在独立的动态链接库(DLL)中。如果对于同一事件(如鼠
标消息)既安装了线程钩子又安装了系统钩子,那么系统会自
动先调用线程钩子,然后调用系统钩子:
(5)钩子会使系统变慢,因为它增加了系统对每个消息的
处理量。仅在必要时才安装钩子,而且在不需要时应尽快移除。
1.2
Windows系统中HooK(钩子)机制的使用步骤
使用HOOK机制可以分为定义钩子函数、安装钩子和卸载
钩子3步,具体方法如下:
(1)定义钩子函数
钩子函数是一种特殊的回调函数。钩子监视的特定事件发
生后,系统会调用钩子函数进行处理。不同事件的钩子函数的
形式是各不相同的,此处以鼠标钩子函数举例说明钩子函数的
原型:
LRESULTCALLBACK
HookProc(int
nCode,WPARAM
wParam,
LPARAM
IParam);
参数wParam和IParam包含所钩消息的信息,比如鼠标位
置/状态、键盘按键等。nCode包含有关消息本身的信息,比如
是否从消息队列中移出。
先在钩子函数中实现自定义的功能,然后调用函数Call.
NextHookEx,把钩子信息传递给钩子链的下一个钩子函数。
(2)安装钩子
在程序初始化的时候,调用函数SetWindowsHookEx安装钩
子。其函数原型为:
HHOOK
SetWindowsHookEx(int
idHook,HOOKPROC
Ipf.,HIN—
STANCE
hMod,DWORD
dwThreadld);
参数idHook表示钩子类型,和钩子函数类型对应。比如
WH—KEYBOARD表示键盘钩子等。lpfn是钩子函数的地址。
hMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为
NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。
dwThreadld指定钩子所监视的线程的线程号。对于全局(系统)
钩子,该参数为NULL。SetWindowsHookEx返回所安装的钩子
句柄。
(3)卸栽钩子
当不再使用钩子时,必须及时卸载。简单地调用函数
BOOL
UnhookWindowsHookEx(HHOOK
hhk)即可。
2HOOK
API(挂钩API)技术
HOOK
API是指截获特定进程或系统对某个API函数的调
用,使得API的执行流程转向指定的代码。Windows下的应用
程序都有自己的地址空间,它们只能调用自己地址空间中的函
数,所以在HOOKAPI之前,必须将一个可以代替API执行的自
定义函数(一般称这个函数为代理函数)的执行代码注入到目
标进程,然后再想办法将目标进程对该API的调用改为对注入
万方数据
到目标进程中的自定义函数的调用,这样即可实现拦截API函
数。Windows下的应用程序都建立在API函数之上,所以截获
API是一项相当有用的技术,它使得用户有机会干预其他应用
程序的程序流程。
3
HOOK
API时的代码注入方法
注入代码到目标进程是实现拦截API很蕈要的一步。比较
简单的方法是把要注入的代码写到DLL中,然后让目标进程加
载这个DLL。这就是所谓的DLL注入技术。如果在这个被注
入到目标进程的DLL中写一个与所要HOOK的API函数的签
名完全相同的函数(即代理函数),当DLL执行初始化代码的时
候,把目标进程对这个API的调用全部改为对代理函数的调用,
即可实现拦截API函数。通过编程实践可知,DLL注入技术有
以下几种:
3.1使用钩子注入DLL
我们知道,对系统钩子而言,当安装钩子的函数SetWindow-
sHookEx调用成功后,Windows在系统内部对系统中的所有进程
自动调用LoadLibrary函数,强迫它们加载包含钩子函数执行代
码的模块,这就是这些进程能够访问钩子函数的原因。从这里
可以得到一个重要启示,那就是如果我们创建一个系统钩子,并
将包含钩子函数执行代码的模块编译成DLL(当然这个DLL中
还必须包含代理函数的代码),就可以实现DLL的自动注入。
这就是所谓的使用钩子注入DLL。
使用Windows钩子注入特定DLL到其他进程,一般都安装
WH
GETMESSAGE钩子,这是因为Windows下的应用程序大部
分都需要调用GetMessage或PeekMessage函数从消息队列中获
取消息,所以它们都会加载钩子函数所在的DLL。
由于此处安装WH—GETMESSAGE钩子的目的仅仅是让其
他进程加载钩子函数所在的DLL,所以一般仅在钩子函数中调
用CallNextHookEx函数即可,如下面代码所示:
LRESULTWINAPI
GetMsgProc(int
code,WPARAM
wParam,
LPARAM
IParam)
{return::CaUNextHookEx(g_hHook,code,wParam,1Pamm);}
如果要将DLL注入到特定进程中,一般是将该进程中主线
程的线程ID传递给SetWindowsHookEx函数;而如果要将DLL
注入到所有进程中,安装一个系统范围内的钩子即可(将0作
为线程ID传递给SetWindowsHookEx函数)。
3.2
使用注册表注入DLL
若要插入一个DLL到链接系统模块User32.du的进程(一
般GUI程序都要使用User32.d11),可以简单地向下面的注册表
键下添加键值数据。
HKEY—LOCAL—MACHINE\SOImI'WARE、Microsoft\Windows
NT\Cur-
rentVersion\Windows\Applnit—DLLs
键值数据可以是单一的DLL名称,也可以是逗号或空格间
隔的DLL集合。所有这个键指定的DLL将被当前帐户下的每
个应用程序加载,它们是在User32.dll初始化的时候被加载的。
User32读取上面提到的键值,在DLL入口函数DllMain中为这
些DLL调用LoadLibrary函数。
这种方法仅仅对使用User32.dll的应用程序有效;另一个
限制是这个机制仅被Windows2000系列的操作系统支持。通
过注册表向进程插入DLL还有如下不足:
(1)为了激活/取消对进程的插入,不得不重新启动Win—


发布评论