Page 311 - 《软件学报》2024年第6期
P. 311

徐建 等: LibPass: 基于包结构和签名的第三方库检测方法                                                2887


                 的  TPL. 假设  APK  有  m  个包, TPL  本地库的规模  n, 且每个  TPL  最多有  1  个包, 在非混淆情形下, 可以通过包名匹
                 配确定   APK  中引入的  TPL, 其计算复杂度为     m×n . 当  n  较大时, 产生较高的比较代价, 尤其是在混淆情形下, 无法
                 借助于包名实现      TPL  检测, 不得不采用更细粒度的对象进行比较, 如以类为比较对象, 这进一步增加了计算复杂
                 度, 进而影响实用性. 本文旨在确保检测精度的前提下, 提升检测效率, 试图通过缩小                        m  和  n  来达成这一目标, 为
                 此提出的一种基于包结构树和签名的检测方法, 命名为                  LibPass, 其框架如图  2  所示, 整个框架由为     3  个关键组件
                 构成, 包括主模块识别、基于包结构树的候选              TPL  筛选和基于多级签名的检测方法.

                           LibPass                                              基于多级签名的检测
                                                       基于包结构树的                     类签名生成
                               主模块识别         非主模块       候选 TPL 筛选      候选 TPL
                                根包解析                  包结构树构建和整形                    类权重分配

                 Android 应用  包依赖关系发现                    包结构树签名                     相似性度量
                   (*.apk)
                          Online
                 的包名、类名被混淆为无意义的短字符, 编译后的类通过扁平化操作移动到其他包中进行重组, 使得主模块与非
                          Offline
                                                                 TPL 本地库
                                                  图 2 LibPass 的组成框架

                    主模块识别组件负责解耦待分析的             APK, 将其拆分为主模块和非主模块. 该组件引入根包的概念, 将                 APK  的
                 包以更粗粒度的根包形式加以组织, 建立包依赖关系图, 通过依赖强度分析识别主模块. 假设主模块和非主模块分

                 别包含   m 1  和   m 2  个包,   m 1 +m 2 = m , 通过主模块识别可以过滤掉   m 1  个包, 成对比较计算复杂度降为  m 2 ×n . 对于本
                 地库中的   TPL, 以离线方式对其预处理, 识别        TPL  的根包.
                    基于包结构树的候选        TPL  筛选组件负责从庞大的       TPL  本地库中快速搜索可能引入的          TPL. 对待分析  APK  的
                 根包, 将其表示为一棵包结构树. 为了对抗混淆操作以提升检测精度, 对包结构树进行了整形和重命名, 在此基础
                 上提出了一种包结构树签名方法. 对于            TPL  的根包, 同样为其生成包结构树、进行整形和重命名, 最后进行签名,
                 并存储在   TPL  本地库中. 于是, TPL  候选筛选问题转变为        APK  中根包签名与     TPL  中根包签名的哈希值比较问题,
                 有很多现有算法可以快速实现这一目标. 假设筛选出的                  TPL  数目为   n  , 有  n ≪ n , 因此, 细粒度比较对象上进行成
                                                                           ′
                                                                      ′
                                         ′
                 对比较的计算复杂度降为         m 2 ×n  .
                    基于多级签名的细粒度检测组件负责为               APK  非主模块中的根包从候选        TPL  中确定引入的唯一一个       TPL. 该
                 检测过程不再以包作为比较对象, 而是以类为比较对象. 鉴于影响检测精度的主要因素是混淆, 提出了基于类内部
                 信息和类间依赖关系的类签名机制, 同时以              APK  为参照对象, 考虑加权成对比较方法, 以降低混淆对于检测精度
                 的影响. 对于给定的      APK, 通过  LibPass 最终输出该  APK  引入的所有   TPL.
                  2.1   主模块识别
                    Android  平台采用  Java 作为开发语言, 因此无论是主模块, 还是非主模块, 都是以层次包结构形式组织代码的.
                 通常, 每个模块都有自己特有的命名空间, 用于区分不同功能意图的模块. 然而, 在混淆情形下, 主模块和非主模块


                 主模块的边界模糊, 显著增加了          TPL  检测的难度. 因此, 有必要研究主模块识别方法实现主模块与引入的                    TPL  的
                 分离, 从而减少待分析的包, 从而有利于提高检测性能和效率. 本文提出了一种基于元信息和包依赖关系的主模块
                 识别方法, 其基本思路是对于没有混淆的             APK, 采用基于元信息的方式, 而对于混淆的            APK  采用基于包依赖关系
                 的方法实现模块解耦. 采用这一思路的事实依据是研究报告                   [34] 表明不少于  55%  的  APK  是混淆的. 因此, 针对混淆
                 和非混淆的情形, 采用不同的解决方法是直截了当的想法.
                    在非混淆的情形下, 每个        APK  解压后的   AndroidManifest.xml 文件中包含的关于“package”的元信息, 该信息
   306   307   308   309   310   311   312   313   314   315   316