zoukankan      html  css  js  c++  java
  • HOOK启思录---前言:HOOK是一种思想

    在很多人眼里,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更是思想。
    ====================================================
  • 相关阅读:
    win10 访问共享缺少 SMB1协议
    H3C 设置用户和密码
    vim 注释和删除多行
    工商银行贵金属网址
    Team Foundation Server 2008 安装 全程记录
    临时表和表变量 区别
    Windows Server 2003开机自动登录
    索引工作原理
    WebService是什么
    CodeFirst
  • 原文地址:https://www.cnblogs.com/spider518/p/2302296.html
Copyright © 2011-2022 走看看