编程技术记录

世界你好!

基本原理

Contents of (__DATA,__objc_classrefs) sectionContents of (__DATA,__objc_superrefs) section中的类是已经被引用的类,Contents of (__DATA,__objc_classlist) section中的类是整个应用未启动时已经定义好的类列表,那么从后者剔除前者而剩余的类就是应用未启动时没有使用的类;同时考虑到Objective-C的运行时特性,所以还需要人工确认下。

基本过程如下:

解压ipa包

本质是zip包,修改后缀解压就可以了

otool 符号格式化

在mac os shell中运行命令(otool 为Xcode工具包中的工具)

otool  -arch armv7 -ov  应用解压后的目录/Payload/应用名/应用二进制文件  >  otool.txt

上述命令中指定armv7架构,其假设是ipa包一定会有armv7的二进制文件

解析获取 __objc_classlist 类列表

打开 otool.txt文件,搜索__objc_classlist ,找到一个class数据,其基本格式如下

025afc00 0x28b2a24     # 第二个,地址0x28b2a24,是class的唯一地址  
    isa        0x28b2a38
    superclass 0x28b4194  # 父类的地址
    cache      0x0 __objc_empty_cache
    vtable     0x0
    data       0x25b5e0c
        flags          0x194 RO_HAS_CXX_STRUCTORS
        instanceStart  4
        instanceSize   20
        ivarLayout     0x2123649
        layout map     0x13 
        name           0x2123610 BCCallMultiVideoController  #类名字
        baseMethods    0x25b5a88
            。。。

我们需要重点关注类地址superclass 父类地址name 类名,按照这样的格式解析所有的__objc_classlist 从而获得所有定义好的类集合。

搜索__objc_classrefs__objc_superrefs,其基本格式如下

02896b94 0x0 _OBJC_CLASS_$_UIView
02896b98 0x0 _OBJC_CLASS_$_UIScrollView
02896b9c 0x0 _OBJC_CLASS_$_UIColor
02896ba0 0x0 _OBJC_CLASS_$_NSNumber
02896ba4 0x0 _OBJC_CLASS_$_UIImage
02896ba8 0x0 _OBJC_CLASS_$_NSMutableArray
02896bac 0x28b2a24  # 第二个地址,0x28b2a24,是引用的类

这样我们就获得了应用未启动时所有已经引用的类(从里面剔除系统类)

然后,就是获取__objc_classrefs__objc_superrefs__objc_classlist的差集,需要注意下因为继承而间接被引用的情况。例如__objc_classrefs集合中有一个0x28b2a24,而这个地址在__objc_classlist中对应BCCallMultiVideoController,所以BCCallMultiVideoController被引用了,而BCCallMultiVideoController的父类是0x28b4194,那么类0x28b4194也被引用了,这样追溯直到父类未空或者父类未系统类。

© Beli. All Rights Reserved.