【恶意软件检测】一种基于API语义提取的Android恶意软件检测方法(期刊等级:CCF-B、Q2)

在这里插入图片描述

一种基于API语义提取的Android恶意软件检测方法
A novel Android malware detection method with API semantics extraction

摘要

由于Android框架和恶意软件的持续演变,使用过时应用程序训练的传统恶意软件检测方法在有效识别复杂演化的恶意软件方面已显不足。为了解决这个问题,本文提出了一种新颖的Android恶意软件检测方法,名为API语义提取的Android恶意软件检测方法(AMDASE),它可以有效识别演化的恶意软件实例。首先,AMDASE执行API聚类以获取代表API功能的聚类中心,然后在恶意软件检测之前设计API句子来总结API特征,并使用自然语言处理(NLP)工具获取API句子的嵌入用于聚类。借助API句子,可以有效地提取包含在方法名称等特征中的API语义,这些特征准确地代表了其预期功能,这也使得聚类结果更加准确。其次,AMDASE从每个应用中提取调用图,并通过移除对应于未知功能的节点的同时确保其前驱节点和后继节点之间的连通性,来优化调用图。优化后的调用图可以提取更健壮的API上下文信息,准确地代表每个应用的行为。第三,为了保持对Android恶意软件演变的抵抗力,AMDASE从优化的调用图中提取函数调用对,并将函数调用对中的API抽象为API聚类中获得的聚类中心。最后,使用一键映射生成特征向量,并使用机器学习分类器进行恶意软件检测。我们在一个包含42,154个良性和42,450个恶意应用的数据集上评估AMDASE,该数据集覆盖了七年的开发期。实验结果表明,AMDASE在性能上大大超过了现有的最先进方法,并且老化速度显著减慢。

1. 引言

Android平台的巨大流行助推了Android恶意软件的迅速扩张。尽管机器学习技术在恶意软件检测方面取得了优异的成果(Qiu等,2020年),但恶意软件的持续演变仍然给检测系统带来了巨大挑战(Jordaney等,2017年)。使用过时应用程序训练的分类器难以有效检测在一定时间后出现的新应用,导致检测性能随时间持续下降,这也被称为模型老化。模型老化是由概念漂移引起的,与计算机视觉或自然语言处理(NLP)不同,恶意软件检测的问题域频繁变化,这导致新出现的恶意软件与旧恶意软件之间的特征分布存在差异。恶意软件开发者常通过改变实现方式来维持恶意行为,从而规避检测系统(张等,2020年)。具体来说,演化的恶意软件具有许多未出现在训练集中的API。目前,大多数恶意软件检测方法都基于API调用信息。基于API频率信息的检测方法(杨等,2014年;Arp等,2014年;冯等,2020年)显示出高假阴性率,并容易受到恶意攻击。依赖API上下文信息的检测方法(吴等,2019年;艾伦等,2018年)在识别应用程序表现出的恶意行为方面显示出更高的准确性。然而,由于缺乏适当的方法处理调用图中大量未知功能节点,这种方法在有效提取API上下文信息方面面临挑战。此外,这些现有的检测方法未能考虑API的频繁变化,因此在有效识别演化的恶意软件方面面临挑战。API聚类将具有相似功能的API分组到同一类别中。在恶意软件检测过程中,可以用API聚类中心替换特征向量中的API,以增强分类器识别训练阶段未遇到的API的能力。这种方法有可能减缓分类器性能随时间衰减的速度(张等,2020年)。然而,现有的API聚类方法从包名、参数和返回值等特征中提取API语义,而忽略了方法名和权限等关键特征。通过API聚类增强分类器性能的有限效果可以归因于API语义提取的不足。Mariconti等(2016年)提出了MAMADROID,其中他们采用了一种聚类技术,根据包名对API进行分组。MAMADROID对现有包中新引入的API表现出了抵抗力,通过将它们抽象为包。然而,需要注意的是,同一包中的API可能不一定表现出相似的功能。此外,MAMADROID无法从新包中捕获任何API信息。Pendlebury等(2019年)发现,在消除时间偏差的实验设置下,MAMADROID的F1-Measure从90%以上下降到仅三个月后的58%。为了解决现有恶意软件检测方法中的上述不足,我们提出了一种新颖的Android恶意软件检测方法,名为API语义提取的Android恶意软件检测方法(AMDASE),它可以有效检测演化的恶意软件。首先,我们进行API聚类,以获取代表API功能的聚类中心。我们设计API句子来总结API特征,并使用NLP工具获取API句子的嵌入用于聚类。其次,我们从每个应用中提取调用图,并通过移除未知功能节点的同时保持其前驱节点和后继节点之间的连接来优化调用图。第三,我们从优化的调用图中提取函数调用对,并将调用对中的API抽象为API聚类部分获得的聚类中心。最后,使用一键编码生成特征向量,并使用机器学习分类器进行恶意软件检测。我们在一个包含42,154个良性应用和42,450个恶意应用的数据集上评估AMDASE的检测性能,该数据集覆盖了七年的开发期。AMDASE在2012年至2013年的数据上训练,当检测2014年至2018年的样本时,平均F1-Measure为82.6%。平均F1-Measure比最先进的恶意软件检测方法MAMADROID高出22%。我们的实验结果表明,AMDASE在性能上大大超过了现有的检测方法,并且老化速度显著减慢。本文主要贡献有三点:1. 首先,我们提出了一种基于语义距离的API聚类方法。我们设计API句子来总结API的特征。API句子不仅包含重要的特征,如方法名,概述了API的功能,还将具有不一致特征数量的API统一映射到固定大小的特征向量中。借助API句子,可以有效地提取API的语义,这使得API聚类结果更加准确。2. 其次,我们引入了一种调用图优化方法。这种方法移除了所有未知节点,同时保持了它们的前驱节点和后继节点之间的连接。如果调用图中的任何两个API节点(例如,APIx和APIy)之间存在由所有未知功能节点组成的路径,则在优化的调用图中,APIx直接调用APIy。调用图优化使得提取的API上下文信息能更精确地反映应用的行为模式。3. 最后,我们介绍了AMDASE,这是一种新颖的Android恶意软件检测方法,可以有效识别演化的恶意软件,无需任何类型的重新训练。通过将API抽象为聚类中心,AMDASE对Android框架和恶意软件中的API变化具有抵抗力。

2. 相关工作

机器学习在Android恶意软件检测方面取得了显著进展(吴等,2023年;巴特等,2023年;塔尔维雷伊等,2023年;杨等,2015年;张等,2014年;杨等,2014年;卡尔巴布等,2018年;陈等,2018年;冯等,2020年;王等,2019年,2018年;刘等,2019年;卢等,2021b年)。然而,模型老化的问题一直是一个重大挑战。Pendlebury等(2019年)和Jordaney等(2017年)详细描述了概念漂移在Android恶意软件检测中的普遍现象。研究人员提出了许多解决这一问题的方案,主要可以分为四类:重新训练、应用关系图、异常样本识别和API聚类。

2.1. 基于重新训练的恶意软件检测

“重新训练”一词指的是利用概念漂移样本及其相应标签重新训练分类器的过程。根据标签的不同来源,重新训练的过程可以分为两种类型:真实标签重新训练和伪标签重新训练。真实标签来自恶意软件专家的手动标注。而“伪标签”指的是由恶意软件分类器生成的推断类标签,通常具有对其预测的高度信心。

Grosse等(2017年)提出了一种自适应且可扩展的Android恶意软件检测方法DroidOL。DroidOL系统利用调用图提取应用的敏感行为特征,并在检测过程中利用被误分类的样本及其相应的真实标签更新分类器。因此,DroidOL具有适应Android应用进展的能力。

徐等(2019年)提出了一种基于在线学习的恶意软件检测方法DroidEvolver。DroidEvolver认为,使用不同优化器训练的分类器具有不同的老化速度,因此在训练阶段构建了一个由五种线性在线学习算法组成的模型池。在检测阶段,使用其他未老化模型的预测结果更新老化模型。

基于重新训练的检测方法通常具有以下缺陷:重新训练真实标签需要大量高质量的概念漂移样本,这在有限的时间内难以完成。此外,重新训练真实标签需要大量人力资源进行概念漂移样本的手动标注。伪标签重新训练免去了人力资源手动标注样本的需要,但伴随着两个固有的局限性。首先,一旦预测标签错误,将导致分类器性能急剧下降。另一个缺点是,恶意攻击者可以设计特定样本来利用伪标签重新训练的机制。

2.2. 基于应用关系图的恶意软件检测

应用关系图指的是构建一个以每个应用为主节点的实体关系图,以反映不同应用之间的相似性。Android生态系统经历的是逐渐的演化过程,而不是突变,导致演化的恶意软件与其祖先保持显著的相似性。一旦概念漂移应用被误分类,分类器可能会利用该应用与其祖先节点在应用关系图中的相似性,将其拉回到决策边界。

顾和李(2021年)提出了一种缓解Android恶意软件检测中模型老化的方法。它构建了一个应用关系图,以反映应用之间的演化关系,这个图辅助分类器进行恶意软件检测。

黑等(2021年)提出了一种基于异构图注意网络的Android恶意软件检测方法。在训练阶段,构建了一个应用关系图来模拟应用之间的相似性。然后,使用图神经网络学习应用之间的相似性,并生成用于恶意软件检测的特征向量。在检测阶段,设计了一种增量聚合方法MsGAT++,使得无需更新整个应用关系图即可快速生成特征向量。

基于应用关系图的检测方法通常具有以下缺陷:首先,代码重用是软件开发的重要部分,因为它允许开发者将现有代码用于各种目的。然而,值得注意的是,代码重用的做法不仅限于良性应用,恶意行为者也可能在恶意软件的开发中使用来自良性应用的重用代码。这给利用应用之间的相似性的恶意软件检测方法带来了严重的困难。同时,应用之间的相似性并不反映它们的行为,这对基于应用关系图的检测方法学习恶意软件与良性应用之间行为特征的差异构成了挑战。

2.3. 基于异常样本识别的恶意软件检测

异常样本识别是在检测过程中过滤出概念漂移样本。恶意软件分类器对这些样本的决策通常信心较低,因此需要恶意软件专家的参与,对这些应用进行评估和做出明智的判断。袁等(2022年)提出了一种使用双头神经网络进行概念漂移样本识别的方法。这个神经网络有两个并行的输出层,分别输出应用的预测结果。通过这两个输出层之间的差异来识别概念漂移样本。Karbab和Debbabi(2021年)提出了一种自适应的Android恶意软件检测方法。分类器在对概念漂移样本做出决策时通常信心较低,因此在恶意软件检测过程中会过滤掉低信心样本。异常样本识别可以大大提高检测方法的有效性,但它仅限于识别概念漂移样本,而不是演化的恶意软件检测。

2.4. 基于API聚类的恶意软件检测

API聚类将具有相似功能的API分组到同一类别中。在恶意软件检测过程中,用API聚类中心替换特征向量中的API可以增强检测方法对API频繁变动的抵抗力。MAMADROID(Mariconti等,2016年)通过包名对API进行聚类。通过将API调用抽象为包,MAMADROID对现有包中新出现的API具有抵抗力。然而,同一包中的API不一定执行相似的功能(张等,2020年)。此外,MAMADROID无法从新包中捕获任何API信息。张等(2020年)提出了APIGRAPH,一种通过API聚类增强现有Android恶意软件分类器的方法。首先,APIGRAPH从Android官方文档中提取信息,构建实体关系图。然后使用TransE(范德马滕和辛顿,2008年)算法生成实体和关系的嵌入向量。最后,使用k-Means(Syakur等,2018年)算法进行API聚类。作者认为具有相似参数、相似权限、相似包名和相似返回值的API必定具有相似功能。然而,在API语义提取过程中,包含大量语义信息的API方法名被忽略了。雷等(2019年)引入了一种使用API标记的API聚类方法。最初,它将调用图中的每个API分割为标记,包括其家族、包名、类名、方法名、返回值和参数。然后,使用doc2vec(Lau和Baldwin,2016年)对每个API进行编码并生成嵌入。最后,使用k-Means算法完成聚类。这种API聚类方法在API语义提取过程中使用了方法名,但忽略了权限和异常等关键特征。权限在Android系统中极为重要(Au等,2012年)。同时,这种方法从训练集而非API文档中收集API,使得该方法无法识别测试集中出现的新API。徐等(2020年)提出了一种使用调用图中API上下文信息的API聚类方法。这种方法认为表现出相似调用者和被调用者模式的API可能具有类似的功能。因此,设计了一个双层神经网络来捕捉API调用及其上下文信息之间的潜在关系。神经网络中的隐藏层用作反映API语义的嵌入,用于聚类。然而,这种方法使用训练数据和测试数据一起训练神经网络,这是一种严重的数据窥探(Quiring等,2022年)行为。在实际场景中,这种方法无法识别测试集中出现的新API。与其他方法相比,API聚类是解决演化恶意软件检测问题最直接和有效的解决方案。然而,现有的聚类方法在API语义提取过程中忽略了方法名和权限等关键特征,导致聚类结果对分类器性能的提升有限。

3. AMDASE概述

AMDASE是一种使用API上下文信息的静态恶意软件检测方法。该系统展示了检测演化恶意软件的强大能力。图1展示了AMDASE的框架。它由两部分组成:基于语义距离的API聚类和Android恶意软件检测。

基于语义距离的API聚类生成代表每个API功能的API聚类中心,这在Android恶意软件检测之前完成。基于语义距离的API聚类有四个步骤。首先,从Android官方文档中提取每个API的特征(图1中的步骤a),包括异常、权限、参数、返回值等。其次,根据规定的规则生成API句子(图1中的步骤b)。第三,使用Bert(Jacob等,2019年),一个成熟的NLP模型,对API句子进行编码,以获取每个API的嵌入(图1中的步骤c)。最后,我们使用k-Means算法生成代表API功能的聚类中心(图1中的步骤d),并将具有相似语义的API分组在一起。

Android恶意软件检测过程包括五个步骤。首先,使用FlowDroid(Arzt等,2014年),一个静态分析工具,从每个应用中提取函数调用图(图1中的步骤1)。此外,通过消除代表未知功能的节点,同时确保它们的前驱节点和后继节点之间的连接被保持,优化调用图(图1中的步骤2)。进一步,从调用图中提取函数调用对(图1中的步骤3)。在第四步,函数调用对最初被抽象为API聚类对。接下来,我们继续将剩余的方法抽象为它们各自的包。最后,使用一键编码生成每个应用的特征向量(图1中的步骤4)。在最后一步,将特征向量输入机器学习分类器,以预测应用是恶意的还是良性的(图1中的步骤5)。

4. 基于语义距离的API聚类

基于语义距离的API聚类包括四个部分:API特征提取、API句子生成、API句子编码和聚类中心生成。

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-3.png]]

4.1. API特征提取

特征提取是从Android官方文档中提取每个API的特征(Api文档,2023年)。我们研究中使用的特征包括七个不同的类别:包名、类名、方法名、参数、权限、异常和返回值。APIGRAPH的作者提供了收集的Android官方文档和API特征提取的源代码(Apigraph,2023年)。通过复制源代码,我们能够获得所有API及其相应的特征。

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-1.png]]

现有的API聚类方法在API语义提取时忽略了方法名,然而,API的方法名包含大量信息并勾画出API的功能。通过使用NLP模型,可以有效地提取API方法名中嵌入的语义信息,从而提供其预期功能的近似表示。例如,具有方法名如‘getDeviceId’或‘setWifiEnabled’的API。它们的方法名使我们能够轻松理解它们的功能。
表1显示了名为Android.telephony.TelephonyManager.getDeviceId的API的特征提取结果。注意,为了减少一些广泛使用的特征值对API语义提取的影响,我们忽略了int、boolean、String和float等特征值。表1中显示的API以int为参数并返回String。在特征提取过程中忽略了这两个特征值。

除了APIGRAPH中现有的特征提取方法外,我们通过利用它们的驼峰命名法(除了第一个单词,其余单词的首字母都是大写的,如‘setWifiEnabled’和‘sendTextMessage’)将方法名和类名分开为单词来修改API特征。表1中显示的API的方法名为‘getDeviceID’,可以分为三个单词:‘get’、‘Device’和‘ID’,用‘$’分隔。注意,类名和方法名中的一些单词都是大写的,如‘SQL’、‘URL’和表1中的‘ID’,这些单词是缩写,需要额外处理。

4.2. API句子生成

在特征提取完成后,我们将API转换为可以反映其语义信息的嵌入。这部分的问题在于同一特征的值数量不一致。例如,某些API的方法名可以分割成五个单词,而有些API可能只能分割成三个单词。一些API需要权限才能调用,而其他API则不需要。因此,有必要设计一种嵌入方法,既能代表API的语义信息,又能将具有不同特征值数量的所有API统一映射到固定大小的特征向量中,这些特征向量最终用于后续聚类中的距离计算。

为解决这个问题,我们首先将每个API及其特征转换为一个句子,称为API句子。根据特征值的数量,API句子的生成分为常见部分和独特部分。常见部分指所有API都具有且只有一个值的三个常见特征:方法名、类名和包名。常见部分句子生成的规则如下:

method 𝑀𝑒𝑡ℎ𝑜𝑑 from class 𝐶𝑙𝑎𝑠𝑠 from package 𝑃𝑎𝑐𝑘

独特部分有四种类型的特征:权限、异常、参数和返回。当涉及到这些独特特征时,每个API具有不同数量的特征值。表2列出了独特部分句子生成的规则。

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-2.png]]

API句子生成的伪代码显示在算法1中。输入是APIx的七种类型的特征,输出是APIx的API句子𝑆。第1至3行生成API句子中常见特征的相应部分;第4至7行调用算法2生成API句子中独特特征的相应部分;第8行将𝑆中的所有大写字母替换为小写字母;第7行将𝑆中的每个‘$’、‘_’和‘.’替换为一个空格。

算法2显示了API句子生成中独特特征处理的伪代码。算法2由算法1的第4至7行调用。输入是独特特征的特征值列表𝐹𝑒𝑎𝑡𝑢𝑟𝑒𝑠和相应的API句子生成规则𝑅0和𝑅1。输出是与独特特征相对应的API句子的一部分𝑆𝑃𝑎𝑟𝑡。算法2考虑了特征值数量为0或至少为1的两种情况。

在将表1中显示的API及其特征输入算法1后,我们可以获得以下API句子:“method get device id from class telephony manager from package Android telephony use permission read phone state throw none exception use none parameter return none”。

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-4.png]]
![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-5.png]]
![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-6.png]]

4.3. API句子编码

在完成API句子生成后,我们使用预训练的Bert模型对每个API句子进行编码,并取CLS的编码输出作为API语义嵌入。CLS的768维特征向量概括了整个句子的语义信息。Bert是一个广泛认可的预训练模型,在NLP领域的各种基础任务中表现出色(Bengio等,2000年)。Bert在输入序列前添加了一个特殊的词向量CLS。CLS是分类的缩写,可以更全面地融合序列中所有单词的信息。它常用于各种下游任务,包括文本情感识别。Bert具有大量的参数。使用在诸如BooksCorpus和Wikipedia(Jacob等,2019年)等语料库上预训练的Bert可以大大节省计算资源。API句子不仅包含API的重要特征,如方法名和权限,还将具有不一致特征数量的API统一映射到固定大小的特征向量中。借助API句子和Bert的嵌入使用,从API中提取语义不仅依赖于包和参数等特征,还依赖于概述API功能的方法名,这使得API聚类结果更加准确。

4.4. 聚类中心生成

通过Bert嵌入获得的每个API的特征向量大小为768维,这对聚类过程中的距离计算带来了相当大的负担。使用主成分分析(PCA)(Svante等,1987年)来降低维度,考虑的方差比为90%。在降维过程后,每个API获得了66维的特征向量。使用肘部方法(Syakur等,2018年)来确定聚类中心的最佳数量,确定为2000个。最后,执行k-Means聚类算法(Syakur等,2018年)。

当Android官方文档更新时,如添加新的API或更改现有API的特征,聚类结果需要更新。如图2所示,我们只需要生成新增或更改API的API句子,并用Bert对其进行编码以获得它们的嵌入。在聚类过程中,新API被分组到最近的聚类中心,并更新这个聚类中心的坐标。

然而,APIGRAPH(张等,2020年)需要更新实体关系图,并使用TransE(Bordes等,2013年)算法从头开始训练整个图,这会生成所有API的嵌入以进行重新聚类。以从API级别28(A28)更新聚类结果到API级别29(A29)为例,A28中有58,291个API,而在A29中新增了834个API。在更新聚类结果时,我们的API聚类方法只需要处理834个新API。而APIGraph不仅需要处理这834个新API,还需要处理A28中现有的58219个API。本文提出的API聚类方法的更新成本显著低于APIGRAPH。

5. Android恶意软件检测

在本文中,我们介绍了AMDASE,这是一种新颖的Android恶意软件检测方法,能够有效识别演化的恶意软件。图3展示了AMDASE中Android恶意软件检测的框架。Android恶意软件检测包括四个步骤:(1)调用图提取,使用静态分析工具从每个应用中提取调用图。(2)调用图优化,通过删除未知功能节点同时保留它们的前驱节点和后继节点的连通性来优化调用图。(3)特征嵌入,将优化后的调用图映射到特征向量中。最初,从调用图中提取函数调用对。随后,使用聚类中心替换调用对中的API,同时使用包替换其他功能。最终,通过使用一键编码生成特征向量。(4)分类,使用训练过的机器学习分类器预测该应用是良性还是恶意。

5.1. 调用图提取

初始程序涉及使用FlowDroid(Arzt等,2014年),一个广泛使用的静态分析工具,从每个APK文件中提取调用图。调用图是一个树结构,表示应用中的函数调用关系。Android操作系统基于事件驱动模型,其中Android应用中的代码执行由多种事件(例如,触摸屏幕、接收网络消息)触发。与常见的Java和C++代码有明确的执行顺序并从特殊的main()函数开始不同,Android应用中的代码根据触发事件的顺序具有不同的执行顺序。因此,FlowDroid生成一个名为dummyMainMethod()的特殊函数作为调用图的根节点,意味着虚拟主函数(也称为入口函数)。dummyMainMethod()的子节点是对应于不同触发事件的代码。FlowDroid假设这些代码可以按任何可能的顺序执行。

5.2. 调用图优化

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-7.png]]

5.2.1. 未知功能引起的问题

API的全名是应用程序编程接口,是一种特殊类型的调用,实现系统功能,如网络通信、蓝牙使用、相机操作等。除了API,应用中还有大量未知功能和相对较少的其他功能。根据代码保护机制(Schulz,2012年),未知功能可以分为混淆功能(例如,com.a.b.c.e123)和自定义功能(例如,com.xiaomi.mipush.sdk.pushMessageHandler)。其他功能主要用于类初始化(例如,java.io.FileOutputStream.init)。Android官方文档提供了这些功能所属类的记录。调用图,也称为控制流图,表示应用内的调用关系。未知功能、其他功能和API都是调用图中的一个节点。未知功能节点占调用图的绝大多数。现有检测方法有两种处理未知功能的方式:统一抽象和全部保留。统一抽象是将所有未知功能节点抽象为一个名为Unknown的节点。这将严重减少调用图的结构信息。未知功能节点占调用图的绝大多数,抽象所有未知节点后,大量API的前驱和后继节点在调用图中都是Unknown节点。因此,调用图中API的上下文信息被严重损害。全部保留涉及保留调用图中所有未知功能节点。这将产生大量冗余信息。API的数量有限,每个API的使用更加清晰。相比之下,软件开发者有权定义未知功能的名称和用途,这些可以轻易改变。在调用图中保留所有未知功能将严重增加后续检测工作的计算开销,并影响检测方法提取API上下文信息。API上下文信息在准确表示每个应用的行为方面最为有效。本质上,恶意软件检测的相关数据主要来源于调用图中API调用的局部信息。然而,大量未知功能节点严重削弱了提取API上下文信息的能力。

5.2.2. 调用图优化算法

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-8.png]]

为了解决提取API上下文信息的严重困难,我们提出了一种调用图优化方法。这种方法移除几乎无法提取任何有用信息的未知功能节点,同时保留它们的前驱节点和后继节点之间的连通性。如果调用图中任意两个API节点(例如,APIx和APIy)之间存在由所有未知功能节点组成的路径,即APIx通过调用几个未知功能调用APIy。在优化的调用图中,APIx直接调用APIy。未知功能本身不包含任何信息,或者包含的信息很少,几乎无法提取。然而,应保留其调用关系,因为它反映了应用的行为。优化后的调用图中只有三种类型的功能:入口功能、API和其他功能。这三种类型的功能之间的调用关系更准确、更稳健地反映了应用的行为。算法3显示了调用图优化的伪代码。该算法的输入是从应用中提取的调用图和Android官方文档。输出是优化后的调用图。

第2至7行用于过滤图中的关键功能节点,包括入口功能、API和其他功能。第8至9行用于获取打算移除的未识别节点的前驱节点列表和后继节点列表。第10至14行的目的是通过嵌套遍历这两个列表并在调用图中添加由这两个列表中的任意两个节点组成的有向边,以保持未知节点的前驱和后继节点之间的连通性。第15行用于从调用图中移除未知节点。

5.3. 特征嵌入

第三步是将优化后的调用图映射到特征向量中。首先,我们从优化后的调用图中提取函数调用对,包括调用者和被调用者。调用对中的函数可以分为三类:API、入口函数和其他功能。然后,每个API被抽象为第4节中获得的聚类中心。该过程还涉及将其他功能抽象为各自的包,入口函数被指定为保留。通过将API抽象为聚类中心,AMDASE能够抵抗Android框架和恶意软件中API的变化。最后,使用一键编码生成每个应用的特征向量。优化调用图中的聚类调用对的特征值映射到组件一,而其他组件设置为零。

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-9.png]]

5.4. 分类

在分类之前,前一步生成的特征向量维度过大,导致在训练和预测过程中产生显著的计算负担。因此,在分类之前使用PCA(Svante等,1987年)来降低特征向量的维度。PCA可以消除特征空间中的误导信息,如噪声,使分类器能够捕获更稳定和强大的特征。在测试随时间开发的恶意软件时,PCA可以大大提高分类器的性能。Android恶意软件检测的最后一步是使用机器学习分类器进行分类,预测这些应用是良性还是恶意。我们选择k-最近邻(KNN)(Fix和Hodges,1952年)、支持向量机(SVM)(Hearst等,1998年)和随机森林(RF)(Breiman,2001年)作为分类器。这三种算法使用Python库scikitlearn(Scikit-learn,2023年)实现。每个模型通过训练集中的应用的特征向量进行训练,并通过测试集中的应用进行测试。我们使用10折交叉验证来评估AMDASE。

6. 实验与分析

在本节中,我们对AMDASE进行了全面评估,包括以下六个实验。1. 我们评估AMDASE在恶意软件检测上的有效性。2. 我们检查AMDASE检测演化的Android恶意软件的能力。3. 我们评估方法名在API聚类中的影响。4. 我们测量调用图优化的影响。5. 我们展示了AMDASE的运行时间评估。6. 我们通过分析嵌入空间中常用API的接近性,评估API聚类在API语义提取上的能力。

6.1. 实验设置

表3展示了我们实验中使用的数据集的概要,包括42,450个恶意应用和42,154个良性应用。我们使用的apk的MD5是由APIGRAPH的作者(张等,2020年)收集的。我们从三个开放仓库下载恶意软件,包括AndroZoo(Allix等,2016年)、VirusTotal(Virustotal,2023年)和AMD数据集(Wei等,2017年)。所有恶意应用至少被VirusTotal中的15个杀毒引擎标记为恶意。我们从Google Play Store(2023年)收集良性应用,并通过AndroZoo的帮助下载它们。所有良性应用都被VirusTotal中的每个杀毒引擎标记为良性。为了评估AMDASE,我们使用收集的数据集进行10折交叉验证。我们为评估演化恶意软件检测设计了以下两种实验场景:• 场景A。使用2012年至2013年的应用进行十折交叉验证,产生10个训练分类器。我们使用这10个分类器检测2014年至2018年开发的恶意软件,并取检测结果的平均值。• 场景B。使用2013年至2014年的应用进行十折交叉验证,产生10个训练分类器。我们使用这10个分类器检测2015年至2018年开发的恶意软件,并取检测结果的平均值。我们选择以下广泛使用的指标,包括准确率(Accuracy)、精确率(Precision)、召回率(Recall)和F1值(F1-Measure)。准确率的计算公式为: Accuracy = T P + T N T P + T N + F P + F N \text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN} Accuracy=TP+TN+FP+FNTP+TN。在以下公式中,精确率为: Precision = T P T P + F P \text{Precision} = \frac{TP}{TP + FP} Precision=TP+FPTP,召回率为: Recall = T P T P + F N \text{Recall} = \frac{TP}{TP + FN} Recall=TP+FNTP。TP和TN分别代表正确分类为恶意和良性的样本数量,FP和FN分别代表错误地识别为恶意和良性的样本数量。

F 1 = 2 × Precision × Recall Precision + Recall F1 = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}} F1=2×Precision+RecallPrecision×Recall

6.2. 恶意软件检测性能

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-10.png]]

为了评估AMDASE在恶意软件检测上的有效性,我们使用同一年开发的样本对AMDASE进行了训练和测试。我们对表3中描述的七个数据集进行了10折交叉验证。表4展示了不同方法在每个数据集上的检测性能。在SVM、RF和KNN中,AMDASE使用RF取得了最佳性能。AMDASE在7年的平均F1-Measure达到了96.7%,比MAMADROID(92.7%)和MALSCAN(90.9%)分别高出4.3%和6.4%;AMDASE的平均准确率为96.7%,比MAMADROID和MALSCAN分别高出4.3%和6.1%;AMDASE的平均精确率为98.5%,比MAMADROID和MALSCAN分别高出5.5%和5.6%;AMDASE的平均召回率为94.8%,比MAMADROID和MALSCAN分别高出3.2%和6.2%。从表4可以看出,MAMADROID的所有指标随时间缓慢增长。MALSCAN(吴等,2019年)在2012年至2014年间精确率较高,召回率较低,但在2015年至2018年间精确率较低,召回率较高。这种现象可能与Android框架的变化有关,但AMDASE始终能稳定地保持高水平的检测性能,受时间变化的影响较小。

6.3. 演化恶意软件检测性能

为了检验AMDASE在演化恶意软件检测上的表现,我们选择了MAMADROID、AE-MAMADROID(张等,2020年)、MALSCAN和AE-MALSCAN(张等,2020年;吴等,2019年)作为比较方法。AE-MAMADROID和AE-MALSCAN分别代表使用APIGRAPH增强MAMADROID和MALSCAN。在不同的分类器中,AMDASE使用SVM在演化恶意软件检测上表现最佳。如表5所示,AMDASE的F1-Measure显著高于其他方法。在场景A中,2014年至2018年AMDASE的平均F1-Measure达到82.6%,比MAMADROID(67.9%)高出22%。在场景B中,2015年至2018年AMDASE的F1-Measure均高于80%。实验结果证明,使用旧样本训练的AMDASE能有效检测演化的恶意软件。与MAMADROID的API聚类方法相比,后者仅将API抽象为其包,AMDASE充分考虑了API的方法名和权限中包含的丰富语义信息,使聚类结果更有效。在恶意软件检测阶段,AMDASE可以借助调用图优化提取更健壮的反映应用行为的特征。因此,使用旧软件样本训练的AMDASE能有效检测演化的恶意软件,并且老化速度显著减慢。APIGRAPH是现有Android恶意软件分类器的增强。它通过用APIGRAPH中获得的聚类中心替换特征向量中的API,使检测方法对演化的恶意软件具有弹性。MALSCAN通过使用调用图中敏感API的中心性信息来检测恶意软件。敏感API由PScout(Au等,2012年)收集,大多数在2016年后很少使用,因此MALSCAN在2017年的F1-Measure急剧下降。AEMALSCAN使用聚类中心的中心性信息替代敏感API。在APIGRAPH增强MALSCAN后,老化速度放缓。相反,MAMADROID在APIGRAPH增强后,老化速度变得更严重。具体原因将在6.5节进一步分析。

6.4. 方法名在API聚类中的影响

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-11.png]]

API的方法名勾画了API的功能,是API语义提取的重要特征。为了评估方法名对API聚类结果的影响,我们设计了三种基于API聚类的恶意软件检测方法。第一种检测方法是使用本文提出的API聚类方法的AMDASE with one-hot encoding (ASEOH);第二种检测方法是Without Method Name (WMN)。WMN的API聚类方法在生成API句子时忽略方法名,其他步骤与本文提出的API聚类方法相同;第三种检测方法是APIGraph with one-hot encoding (AGOH),使用APIGRAPH提出的聚类方法。这三种检测方法都使用聚类中心的一键编码生成特征向量,并选择KNN、RF和SVM中表现最佳的分类器进行恶意软件检测。我们使用场景A和场景B进行十折交叉验证。表6显示了这三种基于API聚类的检测方法的检测结果。在场景A中,2014年至2018年WMN的平均F1-Measure为58.2%,比AGOH高出19.5%;ASEOH的平均F1-Measure为74.6%,比WMN高出28.2%;AMDASE的平均F1-Measure为82.6%,比ASEOH高出10.7%。在场景B中,2014年至2018年WMN的平均F1-Measure为66.9%,比AGOH高出13.4%;ASEOH的平均F1-Measure为79.0%,比WMN高出18.1%;AMDASE的平均F1-Measure为86.5%,比ASEOH高出9.5%。AGOH和WMN在提取API语义时都没有考虑方法名,因此这两种方法的性能迅速衰减。与AGOH相比,WMN使用Bert挖掘类名和权限等特征中的语义信息,导致其老化速度相对较慢。ASEOH使用的API聚类方法充分利用了方法名中包含的语义信息,因此ASEOH的性能大大优于AGOH和WMN。当我们使用从优化调用图中提取的聚类调用对的一键编码作为特征向量(AMDASE)时,检测性能进一步提高。实验结果表明,方法名在API聚类中起着不可或缺的作用。

6.5. 调用图优化的影响

![[2024.02.一种基于API语义提取的Android恶意软件检测方法_image-12.png]]

调用图优化通过移除所有未知功能节点同时保留它们的前驱节点和后继节点的连通性,使AMDASE能够提取更健壮的特征,这些特征能更好地反映应用的行为。为了衡量调用图优化对AMDASE老化速度的影响,我们比较了有和没有调用图优化的AMDASE的性能(AWOCGOPT)。选择场景A和场景B进行十折交叉验证。表7显示了有和没有调用图优化的AMDASE的检测性能。可以看出,调用图优化在交叉验证中只略微提高了AMDASE的检测性能,但它可以显著提高演化恶意软件检测的性能。在场景A中,2014年至2018年,进行调用图优化的AMDASE的平均F1-Measure为82.6%,比没有进行调用图优化的(52.0%)高出59%。在场景B中,2015年至2018年,进行调用图优化的AMDASE的平均F1-Measure为86.7%,比没有进行调用图优化的(68.1%)高出27%。在6.3节中,APIGRAPH削弱了MAMADROID在演化恶意软件检测上的能力,我们认为这是由于缺乏调用图优化,导致调用图中大量未知功能节点削弱了API上下文信息的提取。与未知功能相比,聚类调用对是可以更好地反映应用行为的关键特征,并且可以使检测方法对恶意软件中API的频繁变化具有弹性。表8展示了MAMADROID、AE-MAMADROID和AMDASE的特征向量中关键特征的数量和比例。
表8显示,MAMADROID中的包调用对平均只占所有特征的41.4%。MAMADROID将API抽象为其包,并使用统一抽象来处理未知功能,而不是调用图优化。未知功能被抽象为自定义或混淆,导致近60%的特征主要是包之间和自定义方法的调用。AE-MAMADROID用聚类中心替换调用对中的API,其他步骤与MAMADROID相同。如表8所示,经过APIGRAPH“增强”后,每年平均只能提取372个聚类调用对,占总特征数量的7.8%。超过92%的特征是聚类中心、自定义方法和混淆方法之间的调用。关键特征比例的巨大减少导致APIGRAPH加速了MAMADROID的老化速度。另一方面,AMDASE每年平均可以提取7685个聚类中心调用对,占特征的57.7%,这表明调用图优化使检测方法能够提取更多代表应用行为模式的关键特征,这对演化恶意软件检测是不可或缺的。

6.6. 运行时间评估

在运行时间评估中使用的设备是配备M1 Pro(8×3.2GHz)芯片和16GB内存的MacBook Pro笔记本电脑。在本节中,我们通过使用表3中列出的数据集随机选取的2000个应用,展示了MAMADROID、MALSCAN和AMDASE的运行时间开销。表9展示了运行时间评估的结果。与AMDASE一样,MAMADROID和MALSCAN都是使用调用图中的API上下文信息的恶意软件检测方法。因此,这三种方法的运行时间可以分为三个阶段:调用图提取、特征提取和分类。

![[Pasted image 20241215233407.png]]

  • 调用图提取。这一阶段从APK文件中提取调用图。MAMADROID和AMDASE都使用Soot(Vallée-Rai等,2010年)进行代码表示,并使用FlowDroid生成调用图,因此这两种方法的时间成本几乎相同(14.345秒和14.297秒)。MALSCAN使用Androguard(Androguard,2023年)生成调用图。与FlowDroid相比,Androguard的时间成本大大降低(3.912秒,约低72.6%)。
  • 特征提取。这一阶段将调用图转换为特征向量。MALSCAN需要计算调用图中敏感API的中心性信息,时间成本最大(3.293秒)。AMDASE需要在此阶段优化调用图并嵌入特征,时间成本为0.974秒。MAMADROID从调用图中抽象函数调用对为包调用对,并构建马尔可夫链来模拟转移概率,耗时最少(0.529秒)。
  • 分类。这一阶段使用训练过的机器学习分类器预测应用是恶意的还是良性的。MAMADROID使用PCA进行降维并使用RF进行检测,时间成本为0.028秒。AMDASE使用PCA进行降维并使用SVM进行检测,时间成本为0.025秒。MALSCAN在此阶段只需要RF进行检测,时间开销最少(0.003秒)。
    MALSCAN专注于在应用商店(如Google Play)中快速扫描大量应用。因此,MALSCAN所需的时间在这三种方法中最少(7.208秒)。MAMADROID和AMDASE的运行时间开销相对较大(14.902秒和15.296秒)。其中,AMDASE的运行时间最长,但考虑到AMDASE的出色检测性能和极其缓慢的老化速度,AMDASE的运行性能是可以接受的。

6.7. API聚类在语义提取上的能力

在本节中,我们通过分析嵌入空间中常用API的接近性来评估API聚类在API语义提取上的能力。我们选择了最常用的200个API,并使用t-SNE(Van der Maaten和Hinton,2008年)算法将嵌入空间中的高维特征向量映射到二维平面上。由于空间限制,图4仅显示了部分可视化结果。在图4中,属于同一聚类中心的API用相同的颜色标记。红色节点是与Android活动生命周期相关的API,黄色节点是与线程活动相关的API,深蓝色节点是与输入输出相关的API,橙色节点是与哈希映射相关的API,浅蓝色节点是与数组内容操作相关的API。可以看出,属于同一聚类中心的API具有相似的功能,而具有不同功能的API被分组到不同的聚类中心。值得注意的是,浅蓝色节点和黄色节点都是属于Android包java.lang的API。这表明MAMADROID使用的聚类方法,仅将API分组到它们的包中,不足以提取API语义。如图4所示,具有相似功能的API之间的欧几里得距离较短。这证明了我们的API聚类方法在语义提取上的有效性。我们的方法可以生成更准确反映API功能的嵌入,使得后续的k-Means聚类算法能更好地将具有相似功能的API分组到同一聚类中心。

7. 讨论

API句子规则

在设计API句子生成规则时,我们发现虽然某些具有不同表达但意义相同的规则,对AMDASE的检测性能可能有一定影响。例如,将“use none permission”更改为“do not use permission”或“use no permission”会削弱AMDASE检测演化恶意软件的能力。可能是因为Bert能从“none”中提取的信息比“not”或“no”更多。

API聚类

API聚类属于无监督学习,没有绝对正确的答案来判断API聚类结果的质量。聚类的有效性只能通过恶意软件检测的性能来反映。本文提出的API聚类方法可以有效延缓分类器的老化速度,使分类器对Android框架中的API变化具有弹性。

混淆技术

恶意软件可能使用混淆技术如打包(Duan等,2018年;Lu等,2020年,2021a年)、反射和动态代码加载(Falsina等,2015年)来规避静态检测。恶意软件开发者可能将API混淆为未知功能。在调用图优化过程中,这些混淆的API会丢失。然而,调用图优化的意图是我们无法从大量未知功能中有效提取有用信息。与良性应用相比,恶意软件通常在调用图优化过程中添加更多API调用对。这些调用对大多与线程活动相关。恶意软件经常伪装成良性应用,并通过多线程活动执行恶意行为。

深度学习分类器

深度学习已广泛用于网络安全。未来,我们将尝试使用DNN或GNN(吴等,2020年)作为恶意软件检测的分类器。本文认为,简单的机器学习分类器(如SVM和KNN)更适合检测概念漂移样本,而更强的分类器(如随机森林)容易导致过拟合现象。这些复杂算法基于它们自身的特点,可以在训练阶段学习到除恶意行为之外的更多相关性,并取得更好的检测结果,这也使它们难以有效检测演化恶意软件。

运行时间

应注意,在6.6节中,MAMADROID和AMDASE在第一阶段的时间成本约占总时间的95%。使用Androguard提取调用图可以大大减少恶意软件检测的时间开销,但同时也会丢失一定量的调用图精度,最终会影响检测性能。如何快速且准确地提取Android应用的调用图仍是未来的重要研究方向。

8. 结论

持续演化的恶意软件的检测是一个重大挑战。为了解决这个问题,我们提出了AMDASE,这是一种新颖的Android恶意软件检测方法,具有API语义提取功能。我们设计API句子来总结重要的API特征,并使用Bert提取API的语义。借助API句子,从API中提取语义信息不再仅依赖于包和参数等特征,还依赖于概述API功能的方法名。为了克服调用图中大量未知功能导致提取API上下文信息的困难,我们提出了一种调用图优化方法,该方法移除调用图中所有未知节点,同时保持它们的前驱节点和后继节点之间的连接。同时,我们将优化后的调用图中的API抽象为代表其功能的API聚类中心,这使得检测方法能够抵抗Android框架和恶意软件中频繁的API变化。我们在一个包含42.2K良性和42.5K恶意应用的数据集上评估了AMDASE的有效性,该数据集覆盖了七年的开发期。实验结果表明,AMDASE在性能上大大超过了现有的最先进的Android恶意软件检测方法,同时也显著降低了老化速度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/64818.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FLTK - build fltk-1.1.10 on vs2019

文章目录 FLTK - build fltk-1.1.10 on vs2019概述笔记buildtest测试程序运行 END FLTK - build fltk-1.1.10 on vs2019 概述 看书上用到了fltk-1.1.10, 用vs2019试试能否正常编译使用? 笔记 build 从官网下载fltk-1.1.10-source.tar.bz2 用7zip解开 fltk-1.1.10-source.…

业财融合,决策有据:工程项目管理的财务新视角

在工程项目管理领域,业财融合正开启全新篇章。传统模式下,业务与财务各自为政,常导致信息滞后、决策盲目。如今,借助先进理念与技术,二者紧密相连。 在项目规划阶段,财务部门依据业务需求与市场趋势&#…

汽车IVI中控开发入门及进阶(44):杰发科智能座舱芯片

概述: 杰发科技自成立以来,一直专注于汽车电子芯片及相关系统的研发与设计。 产品布局: 合作伙伴: 杰发科技不断提升产品设计能力和产品工艺,确保产品达 到更高的质量标准。目前杰发科技已通过ISO9001质 量管理体系与CMMIL3认证。 杰发科技长期合作的供应商(芯片代工厂、…

算法专题——双指针

目录 前言 1、移动0 2、复写零 3、快乐数 4、盛最多水的容器 5、有效三⻆形的个数 6、和为s的两个数字 7、三数之和 8、四数之和 前言 本文主要介绍一些用到双指针的常见算法题。 1、移动0 链接:https://leetcode.cn/problems/move-zeroes/description/…

人工智能与云计算的结合:如何释放数据的无限潜力?

引言:数据时代的契机 在当今数字化社会,数据已成为推动经济与技术发展的核心资源,被誉为“21世纪的石油”。从个人消费行为到企业运营决策,再到城市管理与国家治理,每个环节都在生成和积累海量数据。然而,数…

【Chrome Extension】一、CSDN计时扩展设计

【Chrome Extension】一、CSDN计时扩展设计 重点内容内容脚本 content_scripts 文件目录1、整体目录2、manifest.json3、scripts/content.js4、css/content.css 重点内容 内容脚本 content_scripts 1、manifest.json文件配置 {"manifest_version": 3, # *依赖Chro…

javaEE-线程的常用方法-4

目录 一.start():启动一个线程 调用start()方法 start()方法只能调用一次: java中的API: start()和run()的区别: 二.中断一个线程 中断线程方法1:引入标志位 中断线程方法2:调⽤interrupt()⽅法 抛出的异常: 三.等待一个线程 join() 四、获取线程引用 五…

AI的进阶之路:从机器学习到深度学习的演变(四)

AI的进阶之路:从机器学习到深度学习的演变(三) 五、深度学习的应用领域 深度学习的应用领域广泛,涵盖了计算机视觉、自然语言处理、语音识别和推荐系统等多个方面。以下将详细探讨这些关键应用领域,展示深度学习在不同…

Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版)

Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版) 文章目录 Kubeadm+Containerd部署k8s(v1.28.2)集群(非高可用版)一.环境准备1.服务器准备2.环境配置3.设置主机名4.修改国内镜像源地址5.配置时间同步6.配置内核转发及网桥过滤二.容器运行时Containerd安装(所有节点)…

圣诞快乐(h5 css js(圣诞树))

一,整体设计思路 圣诞树h5(简易) 1.页面布局与样式: 页面使用了全屏的黑色背景,中央显示圣诞树,树形由三层绿色的三角形组成,每一层的大小逐渐变小。树干是一个棕色的矩形,位于三角…

PostgreSQL和Postgis安装

Windows下PostgreSQL和对应的版本的Postgis安装 PostgreSQL安装 1、官网下载地址 https://www.enterprisedb.com/downloads/postgres-postgresql-downloads 2、根据自己的系统下载完成,Windows下可以直接傻瓜式安装就OK 建议不要通过自带的这个程序安装postgis,…

拒绝 Helm? 如何在 K8s 上部署 KRaft 模式 Kafka 集群?

首发:运维有术 今天分享的主题是:不使用 Helm、Operator,如何在 K8s 集群上手工部署一个开启 SASL 认证的 KRaft 模式的 Kafka 集群? 本文,我将为您提供一份全面的实战指南,逐步引导您完成以下关键任务&a…

面向微服务的Spring Cloud Gateway的集成解决方案:用户登录认证与访问控制

🎯导读:本文档详细描述了一个基于Spring Cloud Gateway的微服务网关及Admin服务的实现。网关通过定义路由规则,利用负载均衡将请求转发至不同的后端服务,并集成了Token验证过滤器以确保API的安全访问,同时支持白名单路…

浅析InnoDB引擎架构(已完结)

大家好,我是此林。 今天来介绍下InnoDB底层架构。 1. 磁盘架构 我们所有的数据库文件都保存在 /var/lib/mysql目录下。 由于我这边是docker部署的mysql,用如下命令查看mysql数据挂载。 docker inspect mysql-master 如下图,目前只有一个数…

Ajax中的axios

既然提到Ajax,那就先来说一说什么是Ajax吧 关于Ajax Ajax的定义 Asynchronous JavaScript And XML:异步的JavaScript和XML。 反正就是一句话总结: 使用XML HttpRequest 对象与服务器进行通讯。 AJAX 是一种在无需重新加载整个网页的情况下&…

苹果手机怎么清理空间:拯救你的拥挤手机

在数字生活的海洋中,我们的苹果手机就像一艘小船,载满了照片、应用、视频和各种下载的“宝贝”。随着时间的推移,这艘小船开始变得拥挤,航行速度放缓,甚至有时候直接卡壳。苹果手机怎么清理空间?是时候学会…

三、使用langchain搭建RAG:金融问答机器人--检索增强生成

经过前面2节数据准备后,现在来构建检索 加载向量数据库 from langchain.vectorstores import Chroma from langchain_huggingface import HuggingFaceEmbeddings import os# 定义 Embeddings embeddings HuggingFaceEmbeddings(model_name"m3e-base")#…

C语言 函数嵌套

#include <stdio.h> void new_line() {printf("hehe\n"); } void three_line() {int i 0;for (i 0; i < 3; i){new_line;} } int main() {three_line();return 0; } 函数可以嵌套调用&#xff0c;但不能嵌套定义 链式访问 main有三个参数 //main函数的…

问题解决:发现Excel中的部分内容有问题。是否让我们尽量尝试恢复? 如果您信任此工作簿的源,请单击“是”。

在开发同步导出功能是遇到了如标题所示的问题&#xff0c;解决后遂记录下来供大家参考。 RestController public class XxxController {PostMapping("/export")public BaseResponse export(RequestBody PolicyErrorAnalysisExportReq exportReq, HttpServletRespons…

基于ST STM32MP257FAK3的MP2控制器之工业PLC 方案

简介 1.可编程逻辑控制器&#xff08;PLC&#xff09;是种专门为在工业环境下应用而设计的数字运算操作电子系统。它采用一种可编程的存储器&#xff0c;在其内部存储执行逻辑运算、顺序控制、定时、计数和算术运算等操作的指令&#xff0c;通过数字式或模拟式的输入输出来控制…