在很多人眼里,Hook都是高级程序员才会使用的技术。一年前,我也是。每每看到别人使用了Hook技术就很嫉妒。是的,说嫉妒一点都不夸张。
刚开始,不知道Hook到底是什么技术。或者说,Hook到底是做什么的。Hook的英文是钩子,但是,说实话,我的中文意识中,怎么也不能将钩子和Hook划等同符号。
一个钩子,它在等待我们去往上面挂上我们想要的东西。这点,从最终结果看。确实和这个技术很符合。可问题是,那些钩子在什么地方?我们家门口倒是有几个挂衣服的钩子,可是我要挂其他物件的钩子在哪里呢?
最常听说的就是API HOOK了。有句话说得很有道理,HOOK API是一个永恒的话题。网络上,不知有多少人在追捧这个技术。毕竟,喜欢探险是我们的本能。深入别人的系统,获取别人的信息,修改别人的行为,一直都是我们梦寐以求的。
API HOOK又分为13种,具体参考MSDN。这些当中很多在你对系统内核很感兴趣的时候,非常有用。不过我们经常说的钩子,都是鼠标钩子、键盘钩子、消息钩子。
如果我们只满足于这些钩子,那么钩子也不会发展得这么兴旺了。事实上,除了微软提供的钩子函数外,通过钩子的实现原理,我们还可以实现其他类似的钩子。
我对钩子的深入了解和大多数人可能相反,这得感谢我的超同事。我深入了解钩子的时候,是从Delphi的代码钩子开始的。
Delphi的VCL中有些函数实现可能比较低效,但是又没有提供修改的机会。怎么办呢?大家知道,函数在内存中的表现,就是一段代码,其中不连续部分,使用跳转指令(这点很重要)完成。就是说,我们的代码有这个特性:
代码片段(A+B) = 代码片段A + jump + 代码片段B
正是因为这个特性,我们可以通过一些添加一个跳转,让原想调用“代码片段(A+B)”的代码,实际调用“代码片段A + jump + 代码片段C”。这个特性先简单的说明,以后会详细描述。
话说回来,我们解决低效的方法,就是找一个高效的代码,HOOK原有的低效代码。【我这里希望大家接受我的一个建议,不要关注HOOK细节,如果技术可行,我们就简单说明为HOOK。就像这里我这么描述一样】
慢慢的,发现有时候VCL的类库有一些BUG。发现也可以使用类似方法实现。当然了,这里需要注意类方法和普通方法的参数差异(多一个Sender参数)。
有一个典型的例子,就是在Delphi中,TObject提供了从对象到接口的转换服务(as操作符),但是并没有提供接口到实现对象的转换服务,即由一个接口指针,得到实现此接口的对象的服务。
如果我们知道实现此接口的类,我们可以通过获取对象指针和接口指针的偏移,来获得类实例指针。(偏移请参考TObject的InitInstance函数)
但如果我们从高一点的角度来看,假设我们认为TObject必须有这个服务,那么TObject的设计就是有缺陷的。如果我们修复这个错误呢?那么,这个设计不就符合我们的要求了嘛?
下面是我的超同志曾经提出的一种改写方式:
请注意和原有代码差异:
type
TGetInterfaceFunc = function(Self: TObject; const IID: TGUID; out Obj): Boolean;
const
IID_QueryObject: TGUID = '{AD28C649-509D-40F9-B02B-70CF197ECB3C}';
var
OldGetInterface: TGetInterfaceFunc;
function GetInterface(Self: TObject; const IID: TGUID; out Obj): Boolean;
var
InterfaceEntry: PInterfaceEntry;
begin
if IsEqualGUID(IID_QueryObject, IID) then
begin
Pointer(Obj) := Self;
Result := True;
end
else begin
Result := OldGetInterface(Self, IID, Obj); // OldGetInterface是在HOOK的时候,记录
// 的原有函数的地址。
end;
end;
方法是通过对接口中QueryInterface的基础方法GetInterface进行改写,如果传入的IID等于IID_QueryObject的话,就返回对象指针。最后就是针对VCL,HOOK上面这个方法。
细心的你可能发现,上面列举的例子,我刻意地没有去描述HOOK的原理,而重点在说HOOK的应用,或者说,是在使用HOOK技术来解决问题。
事实上,我更想说的是,我们使用HOOK这种思想来解决问题。s每每想起HOOK的巧妙解决方式,我都非常振奋。也这是因为这些振奋,才使我想写一系列关于HOOK思想的文章。希望大家都能使用HOOK思想去思考问题,而不是只是关注于HOOK技术本身。
现在正在流行的AOP(面向方面编程)思想,也是基于HOOK技术发展起来的。但是,AOP一直强调AOP不只是HOOK!实际上,AOP更注重基于HOOK的切片思想。这正和我的想法一致。
我的最终目标不是把大家引向AOP,而是让大家逐步了解到基于HOOK的一些原则和实践。中间有些章节载自别人的文章,只是希望能够比较详细的描述HOOK思想。
希望读完这系列文章,大家能够理解一句话:HOOK是技术,HOOK更是思想。
阅读(593) | 评论(0) | 转发(0) |