美文网首页
【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
    

    相关文章

      网友评论

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

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