• ios逆向工程-内部钩子(Method Swizzling)


    Method Swizzling(方法调配)

    怎么说呢,先了解什么是钩子为什么用钩子,学过C++的朋友应该清楚,hook就是用来获得(截断/改变)底层调用的方法。这样我们可以自由的修改或者读取一些想要的东西。(个人理解)

    下面是百度百科的解释:钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件

    那ios中我们就用Method Swizzling来实现,为什么说是内部钩子呢,因为需要在工程里实现,我改天会分享外部的。

    ----------------------------------------------凌乱的分割线------------------------------------------

    先了解一下SEL和IMP的概念,

    SEL可以理解为函数名的意思,我们常用的@selector()就是通过字符串获得SEL

    IMP可以理解成函数指针的意思,是能正确读取到函数的内容

    一般是这样的:盗个图

    我们要做的就是把链接线解开,然后连到我们自定义的函数IMP上,如果有需要的话,我们再连回原来的IMP上

    就是这样的:

    如果在执行完IMPn后还想继续调用IMPc的话,只需要在IMPn中调用selectorN就行了。

    ---------------------------------------------凌乱的分割线----------------------------------------

    具体怎么做呢:

    1
    Method origMethod = class_getInstanceMethod(class, origSelector);  //获取SEL的Method

    Method是一个结构体,我们想要的IMP就在里面,看看结构

    1
    2
    3
    4
    5
     struct objc_method {
        SEL method_name                                          OBJC2_UNAVAILABLE;
        char *method_types                                       OBJC2_UNAVAILABLE;
        IMP method_imp                                           OBJC2_UNAVAILABLE;
    }
    1
    IMP origIMP = method_getImplementation(origMethod);  //获取Method中的IMP

    ok,IMP获取到了,连接SEL到别的IMP呢

    1
    2
    BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);  //先增加新方法名SEL+原来的IMP
    IMP method_setImplementation(Method m, IMP imp);                       //然后将原来的method(SEL)重新分配新的IMP
    1
    void method_exchangeImplementations(Method m1, Method m2) //或者可以使用method的交换方法

     

    ---------------------------------------------凌乱的分割线-------------------------------------

    实战,假设我们想知道app跳转都传送了什么值(如应用调用QQ分享什么的),那么我们可以勾取UIApplication的OpenUrl方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #import "KHookObjectWrapper.h"
    #import "UIKit/UIKit.h"
    #import <objc/objc.h>
    #import <objc/runtime.h>
     
    @implementation KHookObjectWrapper
     
    + (void)setup
    {
        //openURL
        Method m = class_getInstanceMethod([UIApplication class], @selector(openURL:));
        class_addMethod([UIApplication class], @selector(hook_openURL:), method_getImplementation(m), method_getTypeEncoding(m));
        method_setImplementation(m, class_getMethodImplementation([self class], @selector(hook_openURL:)));
    }
     
    - (BOOL)hook_openURL:(NSURL *)url
    {
        NSLog(@"hook_openURL:%@", [url absoluteString]);
        return [self hook_openURL:url];
    }

    使用method的交换方法实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #import "KHookObjectWrapper.h"
    #import "UIKit/UIKit.h"
    #import <objc/objc.h>
    #import <objc/runtime.h>
     
    @implementation KHookObjectWrapper
     
    + (void)setup
    {
        //openURL
        Method m = class_getInstanceMethod([UIApplication class], @selector(openURL:));
        Method m2 = class_getInstanceMethod([self class], @selector(hook_openURL:));
         
        class_addMethod([UIApplication class], @selector(hook_openURL:), method_getImplementation(m), method_getTypeEncoding(m)); //为什么要有这句的,因为UIApplication没有hook_openURL方法会奔溃,大家觉得可以讲self的hook_openURL改名成openURL,大家可以试试,也是不行的
         
        method_exchangeImplementations(m, m2);
    }
     
    - (BOOL)hook_openURL:(NSURL *)url
    {
        NSLog(@"hook_openURL:%@", [url absoluteString]);
        return [self hook_openURL:url];
    }
     
    @end

     

    --------------------------------------------------------------------

    另外再加一点,假如你只是想重写类的某些方法,分类也是不错的选择,分类一旦加入工程,不需要包含头文件有会生效,所以请慎重使用

    1
    2
    3
    4
    5
    6
    7
    8
    @implementation UIApplication (test)
     
    - (BOOL)openURL:(NSURL*)url {
        NSLog(@"!!!!!%@", [url absoluteString]);
        return YES;
    }
     
    @end

    当然你没办法重新在掉回原来的IMP了!

  • 相关阅读:
    测试运行效率
    识别字符串中的表达式(续二)
    FireScript在SharePoint中的应用
    加入了静态类的语义分析引擎
    这是我在C#中测试速度的代码
    用自定义函数来实现代理类的实例化
    IF语句多分支识别
    FireScript调用DLL和COM
    JMETER在LINUX安装和使用
    转:Big List Of 20 Common Bottlenecks
  • 原文地址:https://www.cnblogs.com/lkislam/p/4859966.html
Copyright © 2020-2023  润新知