美文网首页iOS 逆向与安全
iOS逆向与安全2.3:代码注入Hook方式

iOS逆向与安全2.3:代码注入Hook方式

作者: looha | 来源:发表于2019-05-17 01:22 被阅读0次

    Method Swizzle

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

    在OC中,SEL 和 IMP之间的关系,就好像一本书的“目录”。
    SEL 是方法编号,就像“标题”一样。
    IMP是方法实现的真实地址,就像“页码”一样。
    他们是一一对应的关系

    Runtime提供了交换两个SEL和IMP对应关系的函数.


    image.png image.png image.png

    通过这个函数交换两个SEL和IMP对应关系的技术,我们称之为Method Swizzle(方法欺骗)

    class_addMethod方式:

    • 利用AddMethod方式,让原始方法可以被调用,不至于因为找不到SEL而崩溃

    class_addMethod 参数:
    class_addMethod(Class _Nullable __unsafe_unretained cls, <#SEL _Nonnull name#>, <#IMP _Nonnull imp#>, <#const char * _Nullable types#>)
    <#SEL _Nonnull name#>:ClassName
    <#IMP _Nonnull imp#> :IMP 方法编号
    <#const char * _Nullable types#>):方法类型(返回值+参数):比如"V@:",可通过method_getTypeEncoding(Method)来获得

    class_replaceMethod方式:

    • 利用class_replaceMethod,直接给原始的方法替换IMP

    method_setImplementation方式:

    • 利用method_setImplementation,直接重新赋值原始的新的IMP
    +(void)load{
        //原始的Method
        old_onNext = method_getImplementation(class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(onNext)));
        class_replaceMethod(objc_getClass("WCAccountMainLoginViewController"), @selector(onNext), new_onNext, "v@:");
           
     
    }
    IMP (*old_onNext)(id self,SEL _cmd);
    //新的IMP
    void new_onNext(id self,SEL _cmd)
    {
        //拿出用户密码!
        UITextField * pwd = [[self valueForKey:@"textFieldUserPwdItem"] valueForKey:@"m_textField"];
        NSLog(@"密码是:%@",pwd.text);
        old_onNext(self,_cmd);
    }
    
    BOOL best_Swizzle(Class aClass, Class bClass,SEL originalSel,SEL swizzleSel){
        
        Method originalMethod = class_getInstanceMethod(aClass, originalSel);
        Method swizzleMethod = class_getInstanceMethod(bClass, swizzleSel);
        BOOL didAddMethod = class_addMethod(aClass, originalSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
        if (didAddMethod) {
            class_replaceMethod(aClass, swizzleSel, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        }else{
            method_exchangeImplementations(originalMethod, swizzleMethod);
        }
        
        return YES;
    }
    
    example
    • 方法交换
    +(void)load{
    
    //获取原方法
      Method URLWithStr = class_getClassMethod(self, @selector(URLWithString:));
        
    //新方法
        Method LHURL = class_getClassMethod(self, @selector(LHURLWithStr:));
        
        //交换
        method_exchangeImplementations(URLWithStr, HKURL);
    }
    
    +(instancetype)LHURLWithStr:(NSString *)str{
        //调用系统原来的方法
        NSURL * url = [NSURL LHURLWithStr:str];
        if (url == nil) {
           str = [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        }
        url = [NSURL HKURLWithStr:str];
        
        return url;
    }
    
    
    

    调试方法

    通过地址对象方法的调用
    [(ClassName*)0x999999999  method];
    
    通过对象方法的调用
    //从textField中取text
    NSString *textString = [[[self valueForKey:@"_textFieldUserPwdItem"] valueForKey:@"m_textField"] performSelector:@selector(text)];
    
    ###
    添加新方法
    +(void)load{
    
      //1.拿到原始的Method
        Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), sel_registerName("onNext"));
    //2.添加新的方法
      BOOL didAdd = class_addMethod(object_getClass(@"ClassName"), @selector(new_onNext), my_next, "V@:");
    
    //3.获取到添加的新方法
     Method newOnNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), sel_registerName("new_onNext"));
    
    //4.交换
        method_exchangeImplementations(onNext, newOnNext);
    
    }
    
    void my_next(id self,SEL _cmd){
        NSString * pwd = [[[self valueForKey:@"_textFieldUserPwdItem"]valueForKey:@"m_textField"] performSelector:@selector(text)];
        NSLog(@"密码是!%@",pwd);//获取到密码
        //调用原来的方法
    
    [self performSelector:@seleceor(new_onNest)];
    }
    
    ###替换方法
    +(void)load{
    
      //1.拿到原始的Method
        Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), sel_registerName("onNext"));
    
    //保存原始IMP 
      old_onNext = method_getImplementation(onNext);
    
    //3.替换方法
    
     class_replaceMethod(objc_getClass("WCAccountMainLoginViewController"),  @selector(onNext), my_next, "v@:");
    }
    
    IMP (*old_onNext)(id self,SEL _cmd);
    
    void my_next(id self,SEL _cmd){
        NSString * pwd = [[[self valueForKey:@"_textFieldUserPwdItem"]valueForKey:@"m_textField"] performSelector:@selector(text)];
        NSLog(@"密码是!%@",pwd);//获取到密码
        //调用原来的方法
    old_onNext(self,_cmd);
    }
    
    ### set方法
    +(void)load{
    
      //1.拿到原始的Method
        Method onNext = class_getInstanceMethod(objc_getClass("WCAccountMainLoginViewController"), sel_registerName("onNext"));
    
    //保存原始IMP 
      old_onNext = method_getImplementation(onNext);
    
    //3.set方法
        method_setImplementation(onNext, (IMP)my_next);
    
    }
    
    IMP (*old_onNext)(id self,SEL _cmd);
    
    void my_next(id self,SEL _cmd){
        NSString * pwd = [[[self valueForKey:@"_textFieldUserPwdItem"]valueForKey:@"m_textField"] performSelector:@selector(text)];
        NSLog(@"密码是!%@",pwd);//获取到密码
        //调用原来的方法
    old_onNext(self,_cmd);
    }
    

    相关文章

      网友评论

        本文标题:iOS逆向与安全2.3:代码注入Hook方式

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