Page 295 - 《软件学报》2025年第7期
P. 295
3216 软件学报 2025 年第 36 卷第 7 期
首先提取新 API 的特征并生成 API 句子; 然后使用 BERT 对 API 句子进行编码并使用主成分分析进行降维,
获得新 API 的嵌入向量; 在聚类过程中只需要将新 API 分配到距离最近的聚类中心并更新该聚类中心的坐标. 而
APIGraph 需要更新实体关系图并使用 TransE 算法重新训练整个实体关系图, 生成所有 API 的特征向量, 再重新
进行聚类. 以 API level 28 更新至 API level 29 为例, API level 28 中有 58 291 个 API, API level 29 新增了 834 个
API. 在更新 API 的聚类结果时, 本文提出的 API 聚类方法只需要处理新增的 834 个 API. 而 APIGraph 不仅需要
处理 834 个新 API, 还需要重新处理 API level 28 中已有的 58 219 个 API. 因此, 本文提出的 API 聚类方法的更新
代价远小于 APIGraph.
4 调用图优化
4.1 问题提出
API 全称为应用编程接口, 是实现系统功能 (例如: 网络通信、蓝牙连接等) 的一类特殊函数. 除 API 外, 软件
中还存在着大量未知函数和少量其他函数, 根据代码保护机制 [ 30 ] 可将未知函数分为自定义函数 (例如:
com.xiaomi.mipush.sdk.PushMessageHandler) 和模糊函数 (例如: com.a.b.c.e123); 其他函数主要是类的初始化函数
(例如: java.io.FileOutputStream.init), 其所属的类出现在安卓官方文档中.
函数调用图也称控制流图, 用于表示软件的函数调用关系. 未知函数、其他函数和 API 在调用图中都是一个
节点, 未知函数节点在调用图节点中占大部分.
现有检测方法对函数调用图中未知函数节点的处理方式分为统一抽象和全部保留.
统一抽象是将未知函数节点统一抽象为一个未知节点, 这种方式严重降低函数调用图的结构信息. 由于安卓
特殊的事件触发机制, 通过静态分析提取的函数调用图不包含函数的执行顺序信息. 对所有未知节点进行统一抽
象后, 大部分 API 的前驱和后继都是未知节点, 这导致函数调用图中 API 的上下文信息被严重降低.
全部保留是将函数调用图中的未知函数节点全部保留, 这种方式产生大量冗余信息. API 数量有限且功能明
确, 因此常被用于描述软件的行为特征. 当前恶意软件检测方法主要基于 API 的上下文信息, 而未知函数的名称和
功能由软件开发者定义和修改, 数量庞大且种类繁多, 难以有效提取软件信息. 将调用图中的未知函数全部保留会
严重增加后续检测工作的计算开销, 影响检测方法提取 API 的上下文信息.
API 上下文信息能更好地反映软件的行为逻辑, 即恶意软件检测应基于函数调用图中以 API 节点为中心的局
部信息. 然而, 在当前安卓生态环境下, 未知函数节点在调用图节点中的占比较大, 且现有检测方法对调用图中未
知函数节点的处理方式造成难以提取 API 上下文信息.
4.2 调用图优化算法
为解决调用图中大量未知函数造成的 API 上下文信息提取困难的问题, 本文提出一种调用图优化方法. 未知
函数本身不包含任何信息, 或者说未知函数中包含的少量信息极难提取, 但未知函数前驱和后继 API 节点之间的
调用关系反映软件的行为逻辑, 这有助于分类器识别恶意软件.
调用图优化方法在删除图中所有未知函数节点的同时, 保留 API 节点之间的连接性. 函数调用图中任意两个
API 节点 (API X 和 API Y ) 之间若存在一条全部由未知函数节点组成的路径, 即 API X 通过调用若干未知函数调用
API Y , 则在优化后的调用图中 API X 直接调用 API Y .
调用图优化算法的伪代码如算法 3 所示. 输入为函数调用图和安卓官方文档, 输出为优化过后的调用图.
● 算法 3 的第 2–7 行: 过滤函数调用图中的关键函数节点, 包括: 入口函数、API 和其他函数, 这些节点之间
的调用关系反映软件的行为逻辑, 应予以保留.
● 算法 3 的第 8/9 行: 获得待删除节点的前驱节点集合和后继节点集合.
● 算法 3 的第 10–14 行: 保持待删除节点的前驱和后继节点之间的连接性, 对待删除节点的前驱和后继节点
进行遍历, 在调用图中添加每个前驱节点和每个后继节点组成的有向边.
● 算法 3 的第 15 行: 从函数调用图中删除未知函数节点.

