关键字 API HOOK
原作者姓名 TopLevel
介绍
本文粗略的介绍了有关API HOOK方面的一些原理,附有源代码,希望能给大家带来帮助。
读者评分 12 评分次数 4
正文
Creator : TopLevel
Create Date : 2003-5-12
API HOOK(API钩子)的目的:
一看到Hook这个字眼,首先我们的脑海里浮现的就是“钩子”两词。对于“钩子”两词,看起来不是那么陌生。反正,对于我来说,至少和它还算个脸熟吧。 :P
不过你对它即使脸生,也没关系。因为在这里我们所指的Hook绝对不同于我们所熟悉的系统钩子。虽然意义不同,但有一点,就是它们目的是一样的 :拦截“控制权”(不知道,意思表达的对不对,要是对的话,就鼓鼓掌)。说白了,就是让系统执行某项动作之前,首先按照我们的意图执行,然后,再继续执行系统默认的动作。(附注:做“贼”要让别人不知道,那才叫“贼”。 ·#¥—…*·#^_^ )
长话短说,在这里的所谓的API HOOK就是指的就是 :系统函数接口的钩子。也就是说,当系统函数进行调用时,首先进入我们指定的函数,然后再执行系统的函数。
API HOOK(API钩子)的原理:
其实,这里边的可以采用多种方法实现我们想要的功能。在这里可以就以Jmp方法的为例进行说明。Jmp方法实现简单且一目明了,很容易理解。
其实Jmp有好几种二进制指令,我们这里是用的0xE9,汇编格式为下:
Jmp XXXX // 其中XXXX为距离当前指令的偏移。
我们知道,系统函数都是以DLL封装起来的,应用程序应用到系统函数时,应首先把该DLL加载到当前的进程空间中,调用的系统函数的入口地址,可以通过GetProcAddress函数进行获取。当系统函数进行调用的时候,首先把所必要的信息保存下来(包括参数和返回地址,等一些别的信息),然后就跳转到函数的入口地址,继续执行。其实函数地址,就是系统函数“可执行代码”的开始地址。那么怎么才能让函数首先执行我们的函数呢?呵呵,应该明白了吧,把开始的那段可执行代码替换为我们自己定制的一小段可执行代码,这样系统函数调用时,不就按我们的意图乖乖行事了吗?其实,就这么简单。Very very简单。 :P
大话说出去了,可仔细一想,并没那么简单。哎,急性子没办法,“江山易改,本性难移”。
一个兄弟问:“Top, 看你愁眉不展的,谁又把砖头当鲜花仍你了?”
Top :“我!·#·%¥·#—(¥,”
Top心想 :“小样,不就是要干的神不知,鬼不觉的吗?不就是,不让它弹出那些可恶的带小红叉叉的对话框吗?还治不了它,K,不混了。”
要想“神不知,鬼不觉“就要做到下面最基本的两点:
1. 把进行拦截的函数原形定义的格式和即将拦截的系统函数原形一致。也就是说,参数和返回值要一致。有且只有这样,才能使我们的拦截操作,对当前进程的健壮性,有最大程度的保障。
2. 保持对系统函数的继续调用。如果没这一点,“神不知,鬼不觉“不仅人不相信,恐怕连鬼也不相信。比如:你拦截了MessageBox这个函数,结果你处理完自己的事情(MyMessageBox),也没继续进行系统函数的处理(MessageBox)一拍屁股,就走了,洋洋自得的样子。殊不知,用户在那傻眼,他(她)很郁闷,怎么对话框它怎么就不见了呢?一定是中木马了。哈哈,你的拦截不成功,连菜菜鸟都算不上的,都知道出问题了。这让我想起一个的广告语:”地球人都知道“。
要想不让它弹出长得不好看的带小红叉叉的对话框,呵呵。就需要SEH(Structure Exception Handle)方面的知识了,本人很菜,略知一二,考虑一般不会出现这种情况,就不打算把得砖头的本钱压在这里了。不过这方面的知识,很重要的。嘻嘻。
废话说了这么多,呵呵。该说些实际的了。下面我们就具体讲一下我们该怎么样定制我们的二进制代码,好让它跳到我们的函数中去。我们的做法是:把系统函数的入口地方的内容替换为一条Jmp指令,目的就是跳到我们的函数进行执行。而Jmp后面要求的是相对偏移,也就是我们的函数入口地址到系统函数入口地址之间的差异,再减去我们这条指令的大小。用公式表达如下:
int nDelta = UserFunAddr – SysFunAddr - (我们定制的这条指令的大小);
Jmp nDleta;
也就是说:如果我们已经挂钩好了系统函数。那么当系统进行系统调用时,首先就碰到我们的Jmp XXXX指令,而这条指令作用就是跳到我们的函数中去执行。记住挂钩系统函数时,必须(强调的说法)把我们要替换的内容保存下来,切记,切记。如果不明白,再想想刚才所说的2。保持对系统函数的继续调用。保存这部分内容就是为了恢复系统函数入口地址的内容,让系统函数得以继续调用。
我们采用的总体流程可概括如下:
à 保存系统函数入口-进入我们的函数-恢复系统函数入口-可以做一些我们想做的操作-调用系统函数-挂接系统函数-保存系统函数入口 à …
图例如下:
未挂接:
挂接后:
XXXX = 我的函数入口指针(地址)- 系统函数入口指针(地址)- sizeof (Jmp XXXX指令的大小);
API HOOK(API钩子)的应用:
屏幕取词,游戏外挂,数据包的抓取等。
具体代码如下(只演示了本进程内的API HOOK).
版权所有 @ 2002~2006 TopLevel Studio All Rights Reserved
(如有转载,劳告知一声)
特此声明:
由于在 21CN 的邮箱不太好用,toplayer@21cn.com作废,有新邮箱,另行通知。欢迎和大家多多交流。
我的新邮箱 :
toplevel@tom.com