iOS逆向之OC反汇编(下)

2021-05-10  本文已影响0人  iOS鑫

本文主要理解OC对象反汇编,以及block常见类型的反汇编


OC反汇编

创建一个Person类,并在main函数中初始化一个Person对象

@interface Person : NSObject

@property(nonatomic, copy) NSString *name;
@property(nonatomic, assign) int age;

+ (instancetype)person;

@end

@implementation Person

+ (instancetype)person{
    return [[self alloc] init];
}

@end

<!--main.m中-->
int main(int argc, char * argv[]) {

    Person *p = [Person person];

    return 0;
}

首先作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发公众号:编程大鑫,不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!

1、静态调试

通过adrp+add获取地址,分别读取x0,x1

2、动态调试
通过一步一步执行汇编,来验证x0、x1是否如静态调试的结果一致?

通过调试发现,是一致的,其实这里的x0、x1就是 objc_msgSend的隐藏参数(id self,SEL _cmd)

下面我们继续调试汇编

/*
 - id *location 指向对象的指针  本质上是 &p(即局部变量地址)
 - id obj 对象
 目的:对一个strong修饰的对象进行retain +1,对一个老的对象进行release
 为什么是指针? 因为函数是值传递,而函数内部需要修改p的值
 */
void
objc_storeStrong(id *location, id obj)
{
    //prev 相当于p ,因为location是 &p
    id prev = *location;
    //第二个参数 == 第一个参数,直接return
    if (obj == prev) {
        return;
    }
    //retain+1
    objc_retain(obj);
    //修改p的值,指向第二个对象
    *location = obj;
    //释放老对象
    objc_release(prev);
}

相当于

Person *p = p1;
p = p2;//此时p1释放,p2retain+1

所以以上汇编中的objc_storeStrong(&p,nil)的实现代码如下

objc_storeStrong(&p,nil){
    id prev = p;
    if nil == p{
        return;
    }
    objc_retain(nil);
    p = nil;//指针指向nil
    objc_release(p);//释放堆空间
}

[[self alloc] init] 优化过程

以上是LLDB动态调试Person *p = [Person person]; //objc_msgSend x0,x1

通过工具看复杂的OC代码

在上述OC代码的基础上增加一些代码,然后再来静态分析

int main(int argc, char * argv[]) {

    Person *p = [Person person]; //objc_msgSend x0,x1
    p.name = @"CJL";
    p.age = 18;

    return 0;
}

Block反汇编

定义一个block

int main(int argc, char * argv[]) {

    void(^block)(void) = ^(){
        NSLog(@"block");
    };
    block();

    return 0;
}

反汇编分析block的目的是想快速定位block的invoke,因为invoke中是实现代码,以下是block的汇编代码

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

然后动态调试查看block的内存结构

如果block引用了外部变量呢?

定义一个block,其中block引用了外部变量,查看此时的汇编代码

int main(int argc, char * argv[]) {
    int a = 10;
    void(^block)(void) = ^(){
        NSLog(@"block -- %d", a);
    };
    block();

    return 0;
}

1、lldb调试

2、静态分析

总结

首先作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发公众号:编程大鑫,不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!

上一篇 下一篇

猜你喜欢

热点阅读