Hook Block Parameter in ObjC

Hook ObjC方法中的传入的block类型的参数,当然,你必须先分析出这个block它本身需要传入什么参数。

比如我现在需要Hook -[ViewController executeBlockOrig:]这个实例方法,我们已经分析出它的唯一一个参数是block类型的,定义如下。

typedef void (^AddBlock)(int a, int b);

可以看出这个block类型本身需要两个int类型的参数。

而block的实质其实就是C函数(不是最准确的描述,但是这样理解起来相对容易),那么给 -[ViewController executeBlockOrig:]这个实例方法传入的则是这个C函数的地址,于是我们构造一个函数签名相同的block再传给那个实例方法即可。

以下直接上代码吧。

//
//  ViewController.m
//  Hook Block Parameter
//
//  Created by Ryza 15/4/23.
//  Copyright (c) 2015年 Ryza. All rights reserved.
//
 
#import "ViewController.h"
#import <objc/runtime.h>
 
@implementation ViewController

#pragma mark
#pragma mark - Hook

static IMP originExecuteBlock = NULL;

/*!
 *  @brief  Hook代码
 *
 *  @param  block 已知具体参数类型的block
 */
 
- (void)executeBlockHook:(void *)block
{
    void (^hookBlock)(int a, int b) = ^(int a, int b){
        printf("[HOOK] Original: a is %d, b is %d\n",a,b);

        /*!
         *  @brief  更改一下a, b的值呀什么的
         */
        a = a * 2;
        b = b * 2;
        printf("[HOOK] Modified: a is %d, b is %d\n",a,b);

        void (^originBlock)(int a, int b);
        long long blockPtr = reinterpret_cast<long long>(block);
        memcpy((void *)&originBlock, (void *)&blockPtr, sizeof(long long));
        originBlock(a,b);
    };
    ((void (*)(id, SEL, void *))originExecuteBlock)(self, NSSelectorFromString(@"executeBlockOrig:"),(__bridge void *)hookBlock);
}

#pragma mark
#pragma mark - Origin
 
typedef void (^AddBlock)(int a, int b);

- (void)executeBlockOrig:(AddBlock)block
{
    block(1,3);
}
 
- (void)appCall
{
    /*!
     *  @brief  调用
     */
    AddBlock p  = ^(int a, int b) {
        printf("Result is %d\n",a+b);
    };
    [self executeBlockOrig:p];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    /*!
     *  @brief  模拟dylib注入
     */
    Method m = class_getInstanceMethod(NSClassFromString(@"ViewController"), NSSelectorFromString(@"executeBlockOrig:"));
    originExecuteBlock = method_getImplementation(m);
    method_exchangeImplementations(m, class_getInstanceMethod(NSClassFromString(@"ViewController"), @selector(executeBlockHook:)));

    /*!
     *  @brief  模拟原有的App调用
     */
    [self appCall];
}
@end
 

2 thoughts on “Hook Block Parameter in ObjC”

  1. 我想请教一下,这段
    void (^originBlock)(int a, int b);
    long long blockPtr = reinterpret_cast(block);
    memcpy((void *)&originBlock, (void *)&blockPtr, sizeof(long long));
    originBlock(a,b);
    我想做成通用的,等外面的方法传一个代码来做对block的动态添加代码块工作,应该需要怎样做?因为我不知道originblock的类型。

    1. 需要先通过其它方式知道originblock的类型才行呢,比如用lldb、Hopper或者IDA之类的来调试/反编译等等

Leave a Reply

Your email address will not be published. Required fields are marked *

twenty − 4 =