美文网首页
Hook Block

Hook Block

作者: coder_my | 来源:发表于2018-12-15 22:44 被阅读35次

    参考:
    Apple Block 源码
    CTObjectiveCRuntimeAdditions
    Aspects

    二级标题

    下载Apple Block打开


    Blocks源码

    Block_private.h文件中

    Block结构

    struct Block_layout {
        void *isa;
        volatile int32_t flags; // contains ref count
        int32_t reserved; 
        void (*invoke)(void *, ...);
        struct Block_descriptor_1 *descriptor;
        // imported variables
    };
    

    Block描述

    #define BLOCK_DESCRIPTOR_1 1
    struct Block_descriptor_1 {
        uintptr_t reserved;
        uintptr_t size;
    };
    
    #define BLOCK_DESCRIPTOR_2 1
    struct Block_descriptor_2 {
        // requires BLOCK_HAS_COPY_DISPOSE
        void (*copy)(void *dst, const void *src);
        void (*dispose)(const void *);
    };
    
    #define BLOCK_DESCRIPTOR_3 1
    struct Block_descriptor_3 {
        // requires BLOCK_HAS_SIGNATURE
        const char *signature;
        const char *layout;     // contents depend on BLOCK_HAS_EXTENDED_LAYOUT
    };
    

    Block的flags

    // Values for Block_layout->flags to describe block objects
    enum {
        BLOCK_DEALLOCATING =      (0x0001),  // runtime
        BLOCK_REFCOUNT_MASK =     (0xfffe),  // runtime
        BLOCK_NEEDS_FREE =        (1 << 24), // runtime
        BLOCK_HAS_COPY_DISPOSE =  (1 << 25), // compiler
        BLOCK_HAS_CTOR =          (1 << 26), // compiler: helpers have C++ code
        BLOCK_IS_GC =             (1 << 27), // runtime
        BLOCK_IS_GLOBAL =         (1 << 28), // compiler
        BLOCK_USE_STRET =         (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE
        BLOCK_HAS_SIGNATURE  =    (1 << 30), // compiler
        BLOCK_HAS_EXTENDED_LAYOUT=(1 << 31)  // compiler
    };
    

    通过NSInvocation调用Block实现Hook

    1. 找到Block的方法签名(NSMethodSignature)
    2. 设置target
    3. 有参数插入参数(下标从1开始)
    4. 调用invoke执行
    5. 如果有返回值调用getReturnValue方法接收返回值

    具体实现步骤(添加前缀不与系统的Block冲突)

    定义Block的结构

    struct GMY_Block_descriptor {
        uintptr_t reserved;
        uintptr_t size;
        
        void (*copy)(void *dst, const void *src);
        void (*dispose)(const void *);
        
        const char *signature;
        const char *layout;     // contents depend on BLOCK_HAS_EXTENDED_LAYOUT
    };
    
    struct GMY_Block_layout {
        void *isa;
        volatile int32_t flags; // contains ref count
        int32_t reserved;
        void (*invoke)(void *, ...);
        struct GMY_Block_descriptor_1 *descriptor;
        // imported variables
    };
    

    在Block中找到关键的flags重新定义使用

    enum {
        GMYBLOCK_HAS_COPY_DISPOSE =  (1 << 25), // compiler
        GMYBLOCK_HAS_SIGNATURE  =    (1 << 30), // compiler
    };
    

    代码

    //定义block
    void (^block)(NSString *) = ^(NSString *str){
        NSLog(@"block: %@", str);
    };
    //转化
    struct GMY_Block_layout *blockLayout = (__bridge struct GMY_Block_layout *)block;
    //根据flags的容错判断
    volatile int32_t blockFlags = blockLayout->flags;
    if (blockFlags & GMYBLOCK_HAS_SIGNATURE) {//判断方法签名
        void *blockDesc = blockLayout->descriptor;
        blockDesc += 2 * sizeof(uintptr_t);//指针偏移
        
        if (blockFlags & GMYBLOCK_HAS_COPY_DISPOSE) {
            blockDesc += sizeof(void (*)(void *dst, const void *src));
            blockDesc += sizeof(void (*)(const void *));//指针偏移
        }
        
        const char *signature = (*(const char **)blockDesc);//根据指针取值
        //由NSInvocation对象调用
        NSMethodSignature *blockSignature = [NSMethodSignature signatureWithObjCTypes:signature];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:blockSignature];
        [invocation setTarget:block];
        NSString *str = @"block";
        [invocation setArgument:&str atIndex:1];
        [invocation invoke];
    }
    

    通过函数指针void (*invoke)(void *, ...);调用Block实现Hook

    代码

    void (^block)(void) = ^{
        NSLog(@"block");
    };
    
    struct GMY_Block_layout *myBlock = (__bridge struct GMY_Block_layout *)block;
    myBlock->invoke(myBlock);
    

    相关文章

      网友评论

          本文标题:Hook Block

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