美文网首页
【iOS】检查类函数是否被覆盖

【iOS】检查类函数是否被覆盖

作者: 24c41111e47b | 来源:发表于2023-02-22 19:45 被阅读0次

检查类函数是否被覆盖,一般包含分类覆盖和hook覆盖,这里给出代码快速检测是否被覆盖


1.检测分类函数列表

在要检测的类中引入头文件

#import <objc/runtime.h>
#import <objc/message.h>

在要检测的类中实现如下函数, 并调用进行打印类函数列表(原类 + 分类)

- (void)runTests

{
    unsigned int count;
    Method *methods = class_copyMethodList([self class], &count);
    for (int i = 0; i < count; i++)
    {
        Method method = methods[i];
        SEL selector = method_getName(method);
        NSString *name = NSStringFromSelector(selector);
//        if ([name hasPrefix:@"test"])

        NSLog(@"方法 名字 ==== %@",name);
        if (name)
        {
            //avoid arc warning by using c runtime

//            objc_msgSend(self, selector);
        }

        NSLog(@"Test '%@' completed successfuly", [name substringFromIndex:4]);

    }
}

2.检测是否被Hook

方法Hook一般是在Load函数中实现的,所以可以在AppDelegate.m中进行检测
实现如下函数

BOOL isSiwwzledOrOverridden(Class cls, SEL selector) {
    
    NSMutableDictionary *offsetDict = @{}.mutableCopy;
    unsigned classCount = 0;
    Class *allClasses = objc_copyClassList(&classCount);
    for (unsigned classIndex = 0; classIndex < classCount; ++classIndex) {
        @autoreleasepool {
            Class cls = allClasses[classIndex];
            //只管UI NS开头的类
            if ([NSStringFromClass(cls) hasPrefix:@"UI"] || [NSStringFromClass(cls) hasPrefix:@"NS"]) {
                unsigned methodCount = 0;
                Method *methods = class_copyMethodList(cls, &methodCount);
                for (unsigned methodIndex = 0; methodIndex < methodCount; ++methodIndex) {
                    Method mtd = methods[methodIndex];
                    NSString *mtdString = [NSString stringWithUTF8String:sel_getName(method_getName(mtd))];
                    //_开头的内部方法忽略
                    if ([mtdString hasPrefix:@"_"]){
                        continue;
                    }

                    IMP imp = method_getImplementation(mtd);
                    int offset = (long) cls - (long) imp;
                    offsetDict[[NSString stringWithFormat:@"[%@ %s]", NSStringFromClass(cls), sel_getName(method_getName(mtd))]] = @(offset);
                }
            }
        }
    }
    
    //省略部分代码。。。
    if (offsetDict){
        NSNumber *num = offsetDict[[NSString stringWithFormat:@"[%@ %s]", NSStringFromClass(cls), sel_getName(selector)]];
        if (num == nil){
            NSLog(@"Could not find selector!");
            return NO;
        }
        IMP imp = [cls instanceMethodForSelector:selector];
        int offset = (long) cls - (long) imp;

        if (offset != [num integerValue])
            return YES;
    }
    return NO;
}

然后调用如下函数检查,这里以检查 UIViewControllerviewDidLoad方法为例

BOOL ret = isSiwwzledOrOverridden([UIViewController class], @selector(viewDidLoad));
// ret YES 表示被Hook或者被覆盖
// ret NO 表示没有被Hook

相关文章

  • Python学习记录day4

    1.内置函数补充 callable(object)检查对象object是否可调用1、类是可以被调用的2、实例是不可...

  • 函数的覆盖,隐藏,重载

    函数的覆盖 1.基类函数必须是虚函数 2.发生覆盖的两个函数必须分别位于基类和派生类中 3.函数名称与函数列表必须...

  • Java对象的创建过程

    检查 首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、...

  • iOS----如何检查域名是否支持ipv6

    一、iOS----如何检查域名是否支持ipv6 iOS----------如何检查域名是否支持ipv6 1.检查你...

  • python中的检查继承

    如果你想看一个类是否是另一个类的子类,可以使用内建的issubclass函数。 '''如果想要检查一个类是否是另一...

  • +(void)load; +(void)initialize;有

    一,load函数调用特点: 当类被引用进项目的时候就会执行load函数(main函数开始执行之前),与这个类是否...

  • iOS类方法load和initialize

    +load 当类被引用进项目的时候就会执行load函数(在main函数开始执行之前),与这个类是否被用到无关,每个...

  • 【深入理解java虚拟机】3. 对象的创建过程

    对象的创建 1. 检查类是否被加载 当jvm执行new 指令时, 会检查 指令的参数是否能再常量池中定位到类的符号...

  • load和initialize方法的区别

    load函数是当类被引用进项目的时候会执行(在main函数执行之前)与这个类是否用到无关,每个类的load函数只会...

  • + (void)load和initialize的区别

    load函数调用特点如下: 当类被引用进项目的时候就会执行load函数(在main函数开始执行之前),与这个类是否...

网友评论

      本文标题:【iOS】检查类函数是否被覆盖

      本文链接:https://www.haomeiwen.com/subject/ifnakdtx.html