iOS逆向0011--HOOK(一)-原理

一、HOOK概述

HOOK(钩子) 其实就是改变程序执行流程的一种技术的统称!

一、什么是钩子hook

   Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的。
钩子(hook)是一种特殊的消息处理机制,钩子可以监视系统或进程中的各种事件消息,
截获发往目标窗口的消息并进行处理。
这样,我们就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,
完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等。

    钩子的种类很多,每种钩子可以截获并处理相应的消息,如键盘钩子可以截获键盘消息,
外壳钩子可以截取、启动和关闭应用程序的消息等。钩子可以分为线程钩子和系统钩子, 
线程钩子监视指定线程的事件消息, 系统钩子监视系统中的所有线程的事件消息。
因为系统钩子会影响系统中所有的应用程序,所以钩子函数必须放在独立的动态链接库(DLL) 中。

    按照我的理解,钩子(hook)就是一个Windows消息的拦截机制,你可以单个进程的消息(线程钩子),
也可以拦截所有进程的消息(系统钩子),对拦截的消息进行自定义的处理。
Windows消息带了一些程序有用的信息,比如Mouse类信息,
就带有鼠标所在窗体句柄、鼠标位置等信息(具体可参考相应的消息定义文档),
拦截了这些消息,就可以做出例如金山词霸一类的屏幕取词功能。

二、钩子的工作原理

在正确使用钩子函数前,我们先讲解钩子函数的工作原理。当您创建一个钩子时,WINDOWS会先在内存中创建一个数据结构,该数据结构包含了钩子的相关信息,然后把该结构体加到已经存在的钩子链表中去。新的钩子将加到老的前面。当一个事件发生时,如果您安装的是一个进程钩子,您进程中的钩子函数将被调用。如果是一个系统钩子,系统就必须把钩子函数插入到其它进程的地址空间,要做到这一点要求钩子函数必须在一个动态链接库中,所以如果您想要使用系统钩子,就必须把该钩子函数放到动态链接库中去。当然有两个例外:工作日志钩子和工作日志回放钩子。这两个钩子的钩子函数必须在安装钩子的线程中。原因是:这两个钩子是用来监控比较底层的硬件事件的,既然是记录和回放,所有的事件就当然都是有先后次序的。所以如果把回调函数放在DLL中,输入的事件被放在几个线程中记录,所以我们无法保证得到正确的次序。故解决的办法是:把钩子函数放到单个的线程中,譬如安装钩子的线程。
几点需要说明的地方:

(1) 如果对于同一事件(如鼠标消息)既安装了线程钩子又安装了系统钩子,
     那么系统会自动先调用线程钩子,然后调用系统钩子。 

(2) 对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。
     当前钩子处理结束后应把钩子信息传递给下一个钩子函数。而且最近安装的钩子放在链的开始,
     而最早安装的钩子放在最后,也就是后加入的先获得控制权。 

(3) 钩子特别是系统钩子会消耗消息处理时间,降低系统性能。
     只有在必要的时候才安装钩子,在使用完毕后要及时卸载。

三、相关函数说明

1、钩子函数
钩子函数指钩子在拦截了消息后,进行对应消息处理的函数,可以通过返回TRUE直接抛弃消息,其原型为:
LRESULT CALLBACK HookProcName(int nCode ,WPARAM wParam,LPARAM lParam)

`参数说明:`
   * nCode -- 包含有关消息本身的信息,比如是否从消息队列中移出(未具体了解,有兴趣可查资料).
   * wParam -- 消息标示,用于判断该消息是那种消息,如WM_MOUSEMOVE,WM_NCMOUSEMOVE.
   * lParam -- 包含所钩消息的信息指针,比如鼠标位置、状态,键盘按键等。

2、创建钩子函数
创建新的钩子函数加入到钩子链中,一般在钩子程序初始化时使用.
HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId)

 返回值:
  * HHOOK -- 钩子句柄,需要保留,等不使用钩子时通过UnhookWindowsHookEx函数卸载钩子
 
参数说明:
  * idHook -- 钩子的拦截消息类型,选择钩子程序的拦截范围,具体值参考文章结尾的消息类型
  *  lpfn -- 消息的回调函数地址,一般是填函数名
  *  hMod -- 钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;
            对于系统钩子,该参数为钩子函数所在的DLL句柄。
            在dll中可通过AfxInitExtensionModule(MousehookDLL, hInstance)获得DLL句柄。
  * dwThreadId -- 钩子所监视的线程的线程号,可通过GetCurrentThreadId()获得线程号。
          对于全局钩子,该参数为NULL(或0)。

3、CallNextHookEx
在钩子函数中使用,将钩子信息传递给钩子链的下一个钩子函数。原型如下:
LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam )

   参数说明:
   hhk -- 钩子句柄。
   nCode、wParam和lParam 是钩子函数对应的入参。

4、卸载钩子函数
当不再使用钩子时,必须及时卸载。简单地调用函数 BOOL UnhookWindowsHookEx( HHOOK hhk)即可。



HOOK抢红包

iOS中HOOK技术的几种方式

1、Method Swizzle

利用OC的Runtime特性,动态改变SEL(方法编号)和IMP(方法实现)的对应关系,达到OC方法调用流程改变的目的。主要用于OC方法

2、fishhook

它是Facebook提供的一个动态修改链接mach-O文件的工具。利用MachO文件加载原理,通过修改懒加载和非懒加载两个表的指针达到C函数HOOK的目的。

3、Cydia Substrate

Cydia Substrate 原名为 Mobile Substrate ,它的主要作用是针对OC方法、C函数以及函数地址进行HOOK操作。当然它并不是仅仅针对iOS而设计的,安卓一样可以用。官方地址:http://www.cydiasubstrate.com/

Cydia Substrate主要由3部分组成:

  • MobileHooker

    MobileHooker顾名思义用于HOOK。它定义一系列的宏和函数,底层调用objc的runtimefishhook来替换系统或者目标应用的函数.
    其中有两个函数:

    • MSHookMessageEx 主要作用于Objective-C方法
     void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP result)
    
    
    • MSHookFunction 主要作用于C和C++函数
     void MSHookFunction(voidfunction,void* replacement,void** p_original)
    
    

    Logos语法的%hook 就是对此函数做了一层封装(越狱开发 Tweak,里面写的就是Logos)

  • MobileLoader

    MobileLoader用于加载第三方dylib在运行的应用程序中。启动时MobileLoader会根据规则把指定目录的第三方的动态库加载进去,第三方的动态库也就是我们写的破解程序.

  • safe mode

    因为APP程序质量参差不齐崩溃再所难免,破解程序本质是dylib,寄生在别人进程里。 系统进程一旦出错,可能导致整个进程崩溃,崩溃后就会造成iOS瘫痪。所以CydiaSubstrate引入了安全模式,在安全模 式下所有基于CydiaSubstratede 的三方dylib都会被禁用,便于查错与修复。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容