美文网首页
消息转发 反汇编伪代码____forwarding___

消息转发 反汇编伪代码____forwarding___

作者: 答案不止一个 | 来源:发表于2020-09-25 15:31 被阅读0次

    消息转发流程

    1. 通过 Hooper 反汇编查找相关代码
    2. idea 查看汇编转换后的伪代码
    int ___forwarding_prep_0___(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
        ...
        rax = ____forwarding___(&stack[0], 0x0);
         // 根据返回值判读,直接要走方法转发流程
        // 当 forwardingTargetForSelector 返回有值的时候(不等于ins本身),走 消息发送历程
        if (rax != 0x0) {
                rax = *rax;
        }
        else {
                rax = objc_msgSend(stack[0], stack[8]);
        }
        return rax;
    }
    
    ____forwarding___
    int ____forwarding___(int arg0, int arg1) {
        // arg1 为 0x0
        rsi = arg1;
        // arg0 位ins
        rdi = arg0;
        r15 = rdi;
        rcx = COND_BYTE_SET(NE); 
        
        if (rsi != 0x0) { 
                r12 = *_objc_msgSend_stret;
        }
        else { // 传入的是0x0
                r12 = *_objc_msgSend;
        }
        rax = rcx;
        // 根据流程下面内容 , rax = object_getClass(rbx); 
        // rbx 是对象指针
        rbx = *(r15 + rax * 0x8);
        rcx = *(r15 + rax * 0x8 + 0x8);
        var_140 = rcx;
        r13 = rax * 0x8;
        // 判断 是否优化过的指针 taggedPonter  末尾是1 
        if ((rbx & 0x1) == 0x0) goto loc_64a2b;
    
    loc_649fb:
        rcx = **_objc_debug_taggedpointer_obfuscator;
        rcx = rcx ^ rbx;
        rax = rcx >> 0x1 & 0x7;
        if (rax == 0x7) {
                rcx = rcx >> 0x4;
                rax = (rcx & 0xff) + 0x8;
        }
        if (rax == 0x0) goto loc_64db8;
    
    loc_64a2b:
    
        var_148 = r13;
        // r12 是 *_objc_msgSend
        var_138 = r12;
        var_158 = rsi;
        // rbx  instance 
        rax = object_getClass(rbx);
        r12 = rax; // 类
        // class 名 char *
        r13 = class_getName(rax);
        // r12 Class 判断类的实例 是否有 forwardingTargetForSelector 方法
        if (class_respondsToSelector(r12, @selector(forwardingTargetForSelector:)) == 0x0) goto loc_64ad7;
    
    // 可以执行 forwardingTargetForSelector,去执行
    loc_64a6c:
        rdi = rbx;
    
        // [ins forwardingTargetForSelector:sel] 返回新的 ins
        rax = [rdi forwardingTargetForSelector:var_140];
    
        // 如果执行之后的返回值位nil 或者 这个对象本身,也跳到 loc_64ad7  执行后续的消息转发 -> methodSignatureForSelector  forwardInvocation 流程
    
        if ((rax == 0x0) || (rax == rbx)) goto loc_64ad7;
    
    // 如果 forwardingTargetForSelector 返回了对象  rax 是返回的对象
    loc_64a89:
        r12 = var_138;
        r13 = var_148;
        if ((rax & 0x1) == 0x0) goto loc_64acb; // taggedpointer 相关
    
    loc_64a9b:
        rdx = **_objc_debug_taggedpointer_obfuscator;
        rdx = rdx ^ rax;
        rcx = rdx >> 0x1 & 0x7;
        if (rcx == 0x7) {
                rcx = (rdx >> 0x4 & 0xff) + 0x8;
        }
        if (rcx == 0x0) goto loc_64db5;
    
    loc_64acb:
        *(r15 + r13) = rax;
        r15 = 0x0;
        goto loc_64df2;
    
    //  ??
    loc_64df2:
        if (**___stack_chk_guard == **___stack_chk_guard) {
                rax = r15;
        }
        else {
                rax = __stack_chk_fail();
        }
        return rax;
    
    loc_64db5:
        rbx = rax;
        goto loc_64db8;
    
    loc_64db8:
        if ((*(int8_t *)__$e48aedf37b9edb179d065231b52a648b & 0x10) != 0x0) goto loc_64f41;
    
    loc_64dc5:
        *(r15 + r13) = _getAtomTarget(rbx);
        ___invoking___(r12, r15);
        if (*r15 == rax) {
                *r15 = rbx;
        }
        goto loc_64df2;
    
    loc_64f41:
        ____forwarding___.cold.4();
        rax = *(rdi + 0x8);
        return rax;
    
    // 当没有 forwardingTargetForSelector 是跳转到这里
    //  判断是否是_NSZombie_,
    loc_64ad7:
    // 判断传入的是否是僵尸对象
        var_138 = rbx;
        if (strncmp(r13, "_NSZombie_", 0xa) == 0x0) goto loc_64e31;
    
    loc_64afa:
    // 再去执行methodSignatureForSelector
    // 会返回true,NSObject 有该方法。Core Foundation 会替换掉NSObject的 methodSignatureForSelector方法。
        rax = class_respondsToSelector(r12, @selector(methodSignatureForSelector:));
        r14 = var_138;
        var_148 = r15;
        if (rax == 0x0) goto loc_64e47;
    
    loc_64b22:
        // 执行methodSignatureForSelector 
        rax = [r14 methodSignatureForSelector:var_140];
        rbx = var_158;
        // 如果返回的是nil,则会跳转到 loc_64eac。 执行 doesNotRecognizeSelector
        if (rax == 0x0) goto loc_64eac;
    
    // 如果 methodSignatureForSelector 有返回数据
    // _forwardStackInvocation ??
    loc_64b45:
        r12 = rax;
        rax = [rax _frameDescriptor];
        r13 = rax;
        if (((*(int16_t *)(*rax + 0x22) & 0xffff) >> 0x6 & 0x1) != rbx) {
                rax = sel_getName(var_140);
                rcx = "";
                if ((*(int16_t *)(*r13 + 0x22) & 0xffff & 0x40) == 0x0) {
                        rcx = " not";
                }
                r8 = "";
                if (rbx == 0x0) {
                        r8 = " not";
                }
                _CFLog(0x4, @"*** NSForwarding: warning: method signature and compiler disagree on struct-return-edness of '%s'.  Signature thinks it does%s return a struct, and compiler thinks it does%s.", rax, rcx, r8, r9, stack[-360]);
        }
        rax = object_getClass(r14);
        rax = class_respondsToSelector(rax, @selector(_forwardStackInvocation:));
        var_150 = r13;
        if (rax == 0x0) goto loc_64c89;
    
    loc_64bdc:
        if (*0x5c2700 != 0xffffffffffffffff) {
                dispatch_once(0x5c2700, ^ {/* block implemented at ______forwarding____block_invoke */ } });
        }
        r15 = [NSInvocation requiredStackSizeForSignature:r12];
        rsi = *0x5c26f8;
        rsp = rsp - ___chkstk_darwin(@class(NSInvocation), rsi, r12, rcx);
        r13 = &stack[-360];
        __bzero(r13, rsi);
        ___chkstk_darwin(r13, rsi, r12, rcx);
        rax = objc_constructInstance(*0x5c26f0, r13);
        var_140 = r15;
        [r13 _initWithMethodSignature:r12 frame:var_148 buffer:&stack[-360] size:r15];
        [var_138 _forwardStackInvocation:r13];
        r14 = 0x1;
        goto loc_64ce6;
    
    loc_64ce6:
        if (*(int8_t *)(r13 + 0x34) != 0x0) {
                rax = *var_150;
                if (*(int8_t *)(rax + 0x22) < 0x0) {
                        rcx = *(int32_t *)(rax + 0x1c);
                        rdx = *(int8_t *)(rax + 0x20) & 0xff;
                        memmove(*(rdx + var_148 + rcx), *(rdx + rcx + *(r13 + 0x8)), *(int32_t *)(*rax + 0x10));
                }
        }
        rax = [r12 methodReturnType];
        rbx = rax;
        rax = *(int8_t *)rax;
        if ((rax != 0x76) && (((rax != 0x56) || (*(int8_t *)(rbx + 0x1) != 0x76)))) {
                r15 = *(r13 + 0x10);
                if (r14 != 0x0) {
                        r15 = [[NSData dataWithBytes:r15 length:var_140] bytes];
                        [r13 release];
                        rax = *(int8_t *)rbx;
                }
                if (rax == 0x44) {
                        asm { fld        tword [r15] };
                }
        }
        else {
                r15 = ____forwarding___.placeholder;
                if (r14 != 0x0) {
                        r15 = ____forwarding___.placeholder;
                        [r13 release];
                }
        }
        goto loc_64df2;
    
    loc_64c89:
        if (class_respondsToSelector(object_getClass(r14), @selector(forwardInvocation:)) == 0x0) goto loc_64f32;
    
    loc_64cab:
        rax = [NSInvocation _invocationWithMethodSignature:r12 frame:var_148];
        r13 = rax;
        [r14 forwardInvocation:rax];
        var_140 = 0x0;
        r14 = 0x0;
        goto loc_64ce6;
    
    loc_64f32:
        rdi = &var_130;
        ____forwarding___.cold.3(rdi, r14);
        goto loc_64f41;
    
    loc_64eac:
        rax = sel_getName(var_140);
        r14 = rax;
        rax = sel_getUid(rax);
        if (rax != var_140) {
                _CFLog(0x4, @"*** NSForwarding: warning: selector (%p) for message '%s' does not match selector known to Objective C runtime (%p)-- abort", var_140, r14, rax, r9, stack[-360]);
        }
        if (class_respondsToSelector(object_getClass(var_138), @selector(doesNotRecognizeSelector:)) == 0x0) {
                ____forwarding___.cold.2(var_138);
        }
        (*_objc_msgSend)(var_138, @selector(doesNotRecognizeSelector:));
        asm { ud2 };
        rax = loc_64f32(rdi, rsi);
        return rax;
    // 
    
    loc_64e47:
        rbx = class_getSuperclass(r12);
        r14 = object_getClassName(r14);
        if (rbx == 0x0) {
                _CFLog(0x4, @"*** NSForwarding: warning: object %p of class '%s' does not implement methodSignatureForSelector: -- did you forget to declare the superclass of '%s'?", var_138, r14, object_getClassName(var_138), r9, stack[-360]);
        }
        else {
                _CFLog(0x4, @"*** NSForwarding: warning: object %p of class '%s' does not implement methodSignatureForSelector: -- trouble ahead", var_138, r14, r8, r9, stack[-360]);
        }
        goto loc_64eac;
    
    // 
    loc_64e31:
        r14 = @selector(forwardingTargetForSelector:);
        ____forwarding___.cold.1(var_138, r13, var_140, rcx, r8);
        goto loc_64e47;
    }
    
    msg_forward.png

    在转发流程中,会判断有没有methodSignatureForSelector 方法,如果用户没有自定义,会执行汇编中的代码。
    其中会有一个 ___methodDescriptionForSelector 然后 调用 class_getInstanceMethod 然后再调用
    就会调用到 lookupimporforward behavor 为2 再次resolve一次

    // Replaced by CF (returns an NSMethodSignature)
    + (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)sel {
        _objc_fatal("+[NSObject instanceMethodSignatureForSelector:] "
                    "not available without CoreFoundation");
    }
    
    // Replaced by CF (returns an NSMethodSignature)
    + (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
        _objc_fatal("+[NSObject methodSignatureForSelector:] "
                    "not available without CoreFoundation");
    }
    
    // Replaced by CF (returns an NSMethodSignature)
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
        _objc_fatal("-[NSObject methodSignatureForSelector:] "
                    "not available without CoreFoundation");
    }
    

    消息转发过程也会调用resolve
    查看调用链


    AC51DDE4A1EFDED5A5454FE1A6571D6C.png

    反汇编查询的代码

    -(void *)methodSignatureForSelector:(void *)arg2 {
        rdx = arg2;
        rdi = self;
        if ((rdx != 0x0) && (___methodDescriptionForSelector([rdi class], rdx) != 0x0)) {
                rax = [NSMethodSignature signatureWithObjCTypes:rdx];
        }
        else {
                rax = 0x0;
        }
        return rax;
    }
    
    function ___methodDescriptionForSelector {
        rbx = rsi; // sel
        stack[-72] = rdi;// self  ins
        if (rdi == 0x0) goto loc_7c6fb;
    
    loc_7c61c:
        r12 = stack[-72]; // ins
        stack[-88] = rbx; // 
        goto loc_7c624;
    
    loc_7c624:
        stack[-60] = 0x0; // 用来存储数量
        rax = class_copyProtocolList(r12, &stack[-60]);
        if (stack[-60] == 0x0) goto loc_7c6b2;
    
    loc_7c63d:
        r13 = 0x0;
        // protocol list
        stack[-80] = rax;
        goto loc_7c644;
    
    loc_7c644:
        // 协议
        r15 = *(rax + r13 * 0x8);
        // cls
        rdi = r12;
        r14 = r12;
        // protocol list
        r12 = rax;
        // ins 是否是metacls false
        rax = class_isMetaClass(rdi);
        // protocol sel isRequiredMethod 
        // protocol_getMethodDescription(proto, aSel, isRequiredMethod, isInstanceMethod)
        rax = protocol_getMethodDescription(r15, rbx, 0x1, rax == 0x0 ? 0x1 : 0x0);
        if (rax != 0x0) goto loc_7c6be;
    
    loc_7c672:
        r15 = *(r12 + r13 * 0x8);
        rax = class_isMetaClass(r14);
        rax = protocol_getMethodDescription(r15, rbx, 0x0, rax == 0x0 ? 0x1 : 0x0);
        r12 = r14;
        if (rax != 0x0) goto loc_7c6cc;
    
    loc_7c69a:
        r13 = r13 + 0x1;
        rbx = stack[-88];
        rax = stack[-80];
        if (r13 < stack[-60]) goto loc_7c644;
    
    loc_7c6ad:
        r15 = 0x0;
        goto loc_7c6d3;
    
    loc_7c6d3:
        rbx = 0x0;
        goto loc_7c6d6;
    
    loc_7c6d6:
        free(rax);
        if (r15 != 0x0) goto loc_7c722;
    
    loc_7c6e3:
        // ins
        rax = class_getSuperclass(r12);
        // cls 父类
        r12 = rax;// cls
        rbx = stack[-88];//
        if (rax != 0x0) goto loc_7c624;
    
    loc_7c6fb:
        rax = class_getInstanceMethod(stack[-72], rbx);
        if (rax != 0x0) {
                rax = method_getDescription(rax);
                r15 = *rax;
                rbx = *(rax + 0x8);
        }
        else {
                rbx = 0x0;
                r15 = 0x0;
        }
        goto loc_7c722;
    
    loc_7c722:
        if (**___stack_chk_guard == **___stack_chk_guard) {
                rax = r15;
        }
        else {
                rax = __stack_chk_fail();
        }
        return rax;
    
    loc_7c6cc:
        r15 = rax;
        rax = stack[-80];
        goto loc_7c6d3;
    
    loc_7c6be:
        r15 = rax;
        rbx = 0x1;
        rax = r12;
        r12 = r14;
        goto loc_7c6d6;
    
    loc_7c6b2:
        if (rax == 0x0) goto loc_7c6e3;
    
    loc_7c6b7:
        r15 = 0x0;
        rbx = 0x0;
        goto loc_7c6d6;
    }
    
    

    相关文章

      网友评论

          本文标题:消息转发 反汇编伪代码____forwarding___

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