一种基于敏感行为识别的安卓应用安全性分析方法技术领域
本发明属于软件工程领域,采用基于安卓应用敏感行为识别的方法来分析安卓应用的安
全性,从源代码出发,能够自动、高效、准确地识别安卓应用中的敏感行为。
背景技术
随着使用智能手机的人群日益增大,智能手机所受的安全威胁也越来越突出。其中,因
为安卓平台的开放性以及安卓应用获取渠道更广泛等原因,安卓平台的智能手机所受的安全
威胁尤为严重。因此,针对安卓平台的恶意应用检测工作一直是工业界和学术界关注的热点。
恶意应用可能会私自发送收费短信,或未经用户允许安装其它应用,或盗取用户账户信
息等,造成用户的隐私泄露、经济损失等问题。已有的恶意应用检测方法主要分为静态分析、
动态分析、机器学习三种。
静态分析是在不执行程序的情况下对程序行为进行分析。静态分析适用范围比较广、实
现较简单,不受应用运行平台的影响,可以事先得出检测结果,但受制于应用中的动态加载
等技术以及隐藏恶意代码的方式不断变化,静态分析存在很多误报或者漏报现象。
动态分析是一种用沙盒或虚拟机模拟程序运行,进而监控、拦截程序运行行为的分析方
法。动态分析的优点是绕过了静态方法遇到的代码动态加载和加密等方面的问题,但同时有
代码覆盖率低、漏报等缺点。
机器学习方法只抓住了程序代码片段中最直观的特征,未涉及代码背后所隐藏的信息。
常用的支持向量机(SupportVectorMachine,简称SVM)方法是一种建立在统计学习理论和
结构风险最小原理基础上的机器学习算法。
恶意应用的行为表现多种多样,也可通过多种方式危害用户,但本质上都可概括为违背
用户意愿对私密数据进行操作的敏感行为。根据恶意应用的此种特征,融合程序分析和机器
学习的方法应该能够更有效、快速地分析出安卓应用的安全性。本发明拟结合软件工程领域
中的程序静态分析方法和机器学习领域中的支持向量机方法,通过程序分析得到代码中隐藏
的信息,再进行数据挖掘,从而获得最能表征恶意应用的特征及其取值,最终得到安卓应用的
安全性评估数据。
发明内容
本发明提供了一种基于安卓应用源代码敏感行为识别的安卓应用安全性分析方法,即:
分析应用UI文本所提供的信息、其所触发的敏感行为以及应用的允许请求,将以上信息作为
特征,结合支持向量机的方法,分析应用安全性,提升恶意应用检测的准确率。
本发明的技术方案为:事先将安卓应用反编译得到Java代码,根据其Java代码找出代
码中的敏感行为,即UI组件会触发何种敏感API对哪些敏感信息进行操作,然后将是否包
含某种敏感行为以及是否包含某种允许请求作为该决定安卓应用安全性的特征;分析已知安
全性的安卓应用,得到其特征,使用支持向量机算法对数据集进行训练;根据训练结果,由
未知安全性的安卓应用的特征值分析该安卓应用的安全性。为表述清楚,首先给出如下定义。
定义1:敏感数据是指能对用户隐私、财产甚至人身安全产生威胁的信息,如手机中的
信息、通讯录、账户信息等;
定义2:敏感API是指安卓系统中会对用户敏感信息进行相关操作的API;本专利中主
要关注的敏感API包括与信息发送、打电话、网络链接、应用安装、外设使用相关的API,
例如SendTextMessage()、包含actionandroid.intent.action.CALL的startActicity()、
URL.openConnection()等;
定义3:敏感行为是指用户与操作界面UI进行交互后触发了一些敏感API、对某些敏感
数据进行相关操作的行为,表示为一个三元组(UIFun,SenAPI,SenData),其中UIFun表示与
用户交互的UI组件(一般为按钮等),SenAPI表示与UI交互后所触发的敏感API,SenData
表示敏感API所操作的敏感信息;
本发明技术方案具体包括下列步骤:
1)源代码的获取与分析
步骤1)-1:将安卓应用解压,得到dex文件、manifest文件和与布局相关的xml文件,
使用dex2jar工具将dex文件反编译得到jar包,由jar包可获取应用的安卓代码,同时使用
apktool工具反编译manifest.xml文件以及与布局相关的xml文件。
步骤1)-2:根据步骤1)-1所得代码,构建CFG控制流图以及函数调用关系图,以便
后续的程序分析,具体内容由Datalog语言(Datalog是一种应用在人工智能及程序分析等领
域、具有符号处理和逻辑推理能力的计算机程序设计语言)表示如下。
hasSenAPI(F,SenAPI,L):程序L行处存在函数F,F中调用了敏感API(SenAPI);
hasSenData(L,SenData):程序L行处对敏感数据SenData进行了操作;
directInvoke(F*,F′,L):在程序L行处函数F*直接调用了函数F′;
indirectInvoke(F*,F′):在事件驱动的环境下,函数F′是F*的最终目标;
isIntent(L1,X):程序L1行处定义的参数X的类型是Intent;
intentInitial(L2,X,Y):程序L2行处进行了参数X的初始化,且初始化的第一个真实参
数为Y;
iccInvoke(F*,L,X):在程序L行处函数F*使用了Intent类型的参数X调用了其它函
数;
inComponent(F′,Y):函数F′在组件Y内。
2)敏感行为的获取
根据1)中所得信息,通过以下Datalog语言表示的规则,可获取安卓应用的敏感行为
(UIFun,SenAPI,SenData),其中UIFun代表与UI相关的函数。(符号:-表示由符号右边
可推导得到符号左边。)
invoke(F*,F′,L):-directInvoke(F*,F′,L):由于F*在程序L行处直接调用了F′,可以推
导出F*在程序L行处调用了F′;
invoke(F*,F′,L):-isIntent(L1,X)&intentInitial(L2,X,Y)&iccInvoke(F*,L,X)&
inComponent(F′,Y):此条规则基于安卓应用中的Intent传递机制,F*在程序L行处使用了Intent
类型的参数X来进行组件内的通讯,X的类型在程序L1行处定义为Intent,X在程序L2行
进行初始化,初始化的第一个真实参数为Y,同时组件Y中包含函数F’,由此可推导出F*
在程序L行处调用了程序F’;
invoke(F*,F′,L):-invoke(F*,F,L)&indirectInvoke(F,F′):由于F*在程序L行处调用了F
且F不直接调用F′,可以推导出F*在程序L行处调用了F′;
invoke(F*,F,L):-invoke(F*,F,L)&invoke(F,F′,L′):由于F*在程序L行处调用了F且F
在程序L′行调用了F′,可以推导出F*在程序L行处调用了F′;
以上四条规则为函数之间调用关系的分析。
hasSenAction(F*,SenAPI,SenData,L):-hasSenAPI(F*,SenAPI,L)&hasSenData(L,
SenData):由于F*在程序L行处存在SenAPI以及在程序L行处存在SenData,可以推导出在
程序L行处F*使用SenAPI对SenData进行了相关操作;
hasSenAction(F*,SenAPI,SenData,L):-hasSenAction(F′,SenAPI,SenData,L′)&
invoke(F*,F′,L):由于在程序L′行处F′使用SenAPI对SenData进行了相关操作以及F*在程序
L行处调用F′,可以推导出在程序L行处F*使用SenAPI对SenData进行了相关操作;
以上两条规则为函数是否会触发敏感行为的分析。
3)UI文本的提取
根据步骤1)中所得的Java代码和与布局相关的XML文件,可以得到UI组件上的文本
信息、UIText,将步骤2)中所得的敏感行为(UIFun,SenAPI,SenData)中的UIFun替换为其
组件上的文本UIText。如若其组件上没有文本,则记为“NULL”;如若UIFun本身为NULL,
则不进行任何处理。
4)敏感行为数据的处理
由步骤3)中的操作,可以得到安卓应用中存在的敏感行为(UIText,SenAPI,SenData)。
但由于原始数据所提供的信息过于琐碎,需要进行以下处理。
步骤4)-1:去除UITxet所包含的标点符号,如若UIText所包含的文本字符数大于L
(L为UI按钮上文本的最大字符数),将UIText记为“Long”。
步骤4)-2:根据SenAPI所属的操作种类,将SenAPI替换为所属的SenAct,具体包括:
SendMessage(发信息)、Call(打电话)、Intemet(上网)、Install(安装应用)、UseDevice
(使用诸如摄像头、GPS等外设)。
步骤4)-3:如若SenAct的值不为Intemet,则将其对应的SenData设为“DEFAULT”;
如若SenAct的值为Intemet,根据其对应的SenData所属的数据类型,将其替换为Message
(信息)、AddressBook(通讯录)、UserAccount(用户账户信息)、SensitiveFile(私密
文件)等。
5)特征值的选取
分别从GooglePlay、豌豆荚、恶意应用收集网站上获取安卓应用,分析这些应用所包含
的敏感行为以及manifest.xml文件中所包含的允许请求。将安卓应用是否存在某种敏感行为
(UIText,SenAct,SenData)作为特征之一:若存在该种敏感行为,则特征值设为“1”,否则
设为“0”;将mainifest文件中是否存在某种permission请求也作为特征之一:若存在该种
permission请求,则特征值设为“1”,否则设为“0”。
因此,可以将安卓应用的特征表示为:敏感行为特征1,敏感行为特征2,……,permission
请求特征1,permission请求特征2,……。
6)训练数据集的构成
为已知安全性的安卓应用的特征数据添加安全性标签:若为恶意应用,则安全性标签设
为“0”,否则设为“1”。
最终得到的一行数据包括如下信息:安卓应用名称,唯一标识码,敏感行为特征1,敏
感行为特征2,……,permission请求特征1,permission请求特征2,……,安全性。训练
数据集则由N行这样的数据构成(N为所搜集已知安全性安卓应用的数量)。
7)安全性的分析
对已知安全性的应用数据集进行训练,将这些数据视为n维空间中的点(其中n为应用
所有特征的数量),使用支持向量机算法,并结合应用的安全性标签,可以得到一个判断应
用是否为恶意应用的超平面。在此基础上,根据未知安全性安卓应用的特征值,将其视为n
维空间中的一个点,观察该点与超平面的相对位置,判断该应用的安全性。
本发明采用以上技术方案,具有以下优点:
1、有效提高检测安卓恶意应用的准确率:现今的安卓恶意应用检测方法中,静态分析
方法没有很好地结合机器学习方法,机器学习方法中静态分析的应用又很浅显。我们的方法
结合了程序分析方法和机器学习理论,通过对代码进行一定的静态分析而得到特征,将这些
特征作为支持向量机算法的输入,可以有效提高检测安卓恶意应用的准确率。
2、提高了对仅包含Internet这类敏感行为的恶意应用的检测准确率:大部分安卓恶意应
用仅包含Internet类的敏感行为,常规方法很难判断出这样的恶意应用是否恶意,通过分析
UI文本、敏感API以及敏感数据间的关系,能够更有效地检测该类恶意应用。
3、高效:事前完成数据集的训练后,任何未知安全性的安卓应用进入到分析系统后,
只需简短的分析即可得到其特征值,从而分析出该应用的安全性。
附图说明
图1为本发明的结构流程图。
图2为训练数据集的数据结构图。
图3为豌豆荚代码片段所对应的函数调用关系图。
具体实施方式
本发明的流程如图1所示,主体部分是使用敏感行为分析方法的特征提取,所要做的是
通过分析安卓应用的安装文件APK,得到可供支持向量机算法所使用的数据。针对已知安
全性的安卓应用,通过分析得到其特征,将其组织为训练数据集;针对未知安全性的安卓应
用,通过特征分析可以得到除安全性以外的特征,使用这些特征并结合数据训练结果,预测
得到其安全性。
第一步:APK文件无法直接分析,需要解压后获取Manifest.xml、class.dex以及与布局
相关的layout.xml文件。这些文件无法直接作为下一步分析的输入,需要使用工具
dex2jar(http://sourceforge.net/projects/dex2jar/)将class.dex反编译为jar包,从而获得安卓应用
的Java代码;同时我们需要使用工具apktooI(http://ibotpeaches.github.io/Apktool/)对XML文
件进行解码,获得可读的XML文件。
第二步:获得安卓应用的代码后,使用WALA工具(http://sourceforge.net/projects/wala/)
得到控制流图CFG以及函数调用关系图,进一步提取与敏感API、敏感数据及其相关的行
为。由于我们主要关注安卓应用中何种敏感API对何种敏感数据进行操作,我们定义了如下
谓词,寻找代码中的敏感API和敏感数据,用Datalog语言表示。
是否存在敏感API,hasSenAPI(F,SenAPI,L):程序L行处存在函数F,F中调用了敏感
API—(SenAPI)。
是否存在敏感数据,hasSenData(L,SenData):程序L行处对敏感数据SenData进行了操
作。
找到了代码中的敏感API后,我们需要知道这两者在应用中如何传递、何种函数会触发
敏感API对敏感数据进行操作,因此定义如下谓词,以指明函数间的调用关系。
直接函数调用关系,directInvoke(F*,F′,L):在程序L行处,函数F*直接调用了函数F′。
间接函数调用关系,indirectInvoke(F*,F′):在事件驱动的环境下,函数F′是F*的最终目
标。
在安卓中组件之间可以使用ICC(InterComponentCommunication)机制来进行函数调用,
我们定义以下谓词来完整表达使用ICC机制进行函数调用的过程。
是否是Intent,isIntent(L1,X):程序L1行处定义的参数X的类型是Intent。
Intent的初始化,intentInitial(L2,X,Y):在程序L2行处进行了参数X的初始化,且
初始化的第一个真实参数为Y。
使用ICC机制的函数调用,iccInvoke(F*,L,X):在程序L行处,函数F使用了Intent
类型的参数调用了其它函数。
是否在某组件内,inComponent(F′,Y):函数F′在组件Y内。
以下通过代码来具体说明使用ICC机制进行函数调用的一种情况。
上述代码表明:在函数F*中定义了初始化参数为Y和url的Intent类型的参数X,
在语句“startActivity(X);”中启动X,会调用Y中的函数F′,即函数F*通过ICC机制调用
了函数F′。
第三步:获取以上步骤所得到的由Datalog语言所表达的谓词后,我们定义了同样由
Datalog语言所表示的推导规则,将所得到的谓词表达作为输入,可以得到所关注的敏感行
为——UI组件触发了某种敏感API对敏感数据进行了操作,可表示为(UIFun,SenAPI,
SenData)。推导规则表示如下。
推导规则R1,函数间的调用(直接调用关系)invoke(F*,F′,L):-directInvoke(F*,F′,L):
由F*在程序L行处直接调用了F′,可以推导出F*在程序L行处调用了F′。
推导规则R2,函数间的调用(使用icc机制的函数调用关系)invoke(F*,F′,L):-isIntent(L1,
X)&intentInitial(L2,X,Y)&iccInvoke(F*,L,X)&inComponent(F′,Y):此条规则基于安卓应用
中的Intent传递机制,F*在程序L行处使用了Intent类型的参数X来进行组件内的通讯,X
的类型在程序L1行处定义为Intent,X在程序L2行进行初始化,初始化的第一个真实参数
为Y,同时组件Y中包含函数F’,由此可推导出F*在程序L行处调用了程序F’。
推导规则R3,函数调用的传递性(调用关系与间接调用关系),invoke(F*,F′,L):-
invoke(F*,F,L)&indirectInvoke(F,F′):由F*在程序L行处调用了F及F不直接调用F′,推
导出F*在程序L行处调用了F′。
推导规则R4,函数调用的传递性(调用关系与调用关系),invoke(F*,F,L):-invoke(F*,
F,L)&invoke(F,F′,L′):由F*在程序L行处调用了F及F在程序L′行调用了F′,推导出F*
在程序L行处调用了F′。
推导规则R5,是否存在敏感行为,hasSenAction(F*,SenApi,SenData,L):-hasSenAPI(F*,
SenAPI,L)&hasSenData(L,SenData):由F*在程序L行处存在SenAPI以及在程序L行处存
在SenData推导出在程序L行处F*使用SenAPI对SenData进行了相关操作。
推导规则R6,敏感行为在函数间的传递,hasSenAction(F*,SenAPI,SenData,L):-
hasSenAction(F′,SenAPI,SenData,L′)&invoke(F*,F′,L):由在程序L′行处F′使用SenAPI对
SenData进行了相关操作以及F*在程序L行处调用F′,推导出在程序L行处F*使用SenAPI
对SenData进行了相关操作。
第四步:敏感行为(UIFun,SenAPI,SenData)还不能直接作为应用的特征,我们所关注
的是UI组件本身所表达的意图与其所触发的敏感API是否一致,为此我们需要提取UI组
件上的文本。由第一步中所得到的layout.xml文件,我们可以获取UI组件上的文本UIText,
将其替换掉UIFun,我们可以得到敏感行为(UIText,SenAPI,SenData)。
第五步:为了控制训练数据集的规模以及稀疏程度,我们还需要对敏感行为(UIText,
SenAPI,SenData)进行一定处理。
首先,我们主要关注按钮以及跳出对话框的文本,这些文本字符数量相对较少,针对
UIText中字符数量较多的文本,我们将其替换为“Long”。
其次,敏感API数量较多,但绝大多数都可以分到几大类中。我们不需要知道敏感API
具体行为,只需要知晓其功能即可。根据SenAPI所属的操作种类,将SenAPI替换为所属
的SenAct,SenAct包含以下几种:SendMessage(发信息)、Call(打电话)、Internet(上
网)、Install(安装应用)、UseDevice(使用诸如摄像头、GPS等外设)。除上网这种SenAct
外,其它敏感动作所处理的敏感数据类型均确定,我们将其所对应的SenData设为
“DEFAULT”;而针对上网这种敏感动作,根据其对应的SenData所属的数据类型,将其替
换为Message(信息)、AddressBook(通讯录)、UserAccount(用户账户信息)、Sensitive
File(私密文件)等。经过以上处理我们可以得到敏感行为(UIText,SenAct,SenData)。
第六步:通过分析已知安全性的应用,我们可以得知其具有哪些敏感行为(UIText,SenAct,
SenData),将应用是否具有某种敏感行为(UIText,SenAct,SenData)作为特征之一。若具
有该种敏感行为,则该特征的特征值为“1”,否则为“0”。由第一步中所得Mainifest.xml中我
们可以获取应用的允许请求列表,将应用是否具有某种允许请求也作为特征之一。若具有该
种允许请求,则该特征的特征值为“1”,否则为“0”。另外将应用的安全性作为应用的标签,
并赋予应用唯一标识码,这样就构成了训练数据集的一条数据。最终训练数据集的数据结构
如图2所示。
第七步:对已知安全性的应用进行特征提取后,我们需要对未知安全性的应用也进行特
征提取操作,但由于这些应用的安全性未知,我们只可以获取其敏感行为特征及允许请求特
征。然后我们开始分析预测未知安全性的安卓应用,具体方法是使用支持向量机对训练数据
集进行训练,有了训练结果后,就可以通过应用的其它特征来预测其安全性。
下面结合国内著名安卓市场豌豆荚的APK安装文件对本发明的特征提取过程作具体实
施说明。本发明不仅适用于该例。对该应用提取特征的具体过程如下:
第一步:将从互联网上所获取的豌豆荚安装文件apk后缀名更改为zip,解压后获得关
键文件classes.dex、AndroidManifest.xml和位于res文件夹下的layout文件。对其作相应处
理,我们可以得到应用的Java代码和可阅读的XML文件。
第二步:运用工具WALA,分析Java代码,得到函数调用关系图。例如,通过分析如
下代码片段,我们可以得到如图3所示的函数调用关系图。
代码片段:
第三步:通过分析函数调用图,我们可以找出所关注的敏感API和函数调用关系。如图
3所示的函数调用关系,其中的有用信息用Datalog语言表示如下。
hasSenAPI(Fn(),openStream(),20);
directInvoke(Fm(),Fm+1(),16);directInvoke(Fm+1(),Fm+2(),X);…;
directInvoke(Fm+n-m-1(),Fn(),Y);
directInvoke(onClick(),Fm(),09);
第四步:从这些有用信息中我们需要找到应用的敏感行为,即何种UI控件会触发敏感
API,从以上代码片段中找出敏感行为的过程用Datalog语言所表示如下。
根据推导规则R1:Invoke(Fm(),Fm+1(),16);Invoke(Fm+1(),Fm+2(),X);…:-directInvoke
(Fm(),Fm+l(),16);directInvoke(Fm+1(),Fm+2(),X);…;
根据推导规则R1:Invoke(Fm+n-m-1(),Fn(),Y):-directInvoke(Fm+n-m-1(),Fn(),Y);
根据推导规则R1:Invoke(onClick(),Fm(),09):-directInvoke(onClick(),Fm(),09);
根据推导规则R4:Invoke(Fm(),Fn(),16):-Invoke(Fm(),Fm+1(),16)&Invoke(Fm+1(),Fm+2(),
X)&…&Invoke(Fm+n-m-1(),Fn(),Y);
根据推导规则R5:hasSenAction(Fn(),openStream(),NULL,20):-hasSenApi(Fn(),
openStream(),20);
根据推导规则R4:Invoke(onClick(),Fn(),09):-Invoke(onClick(),Fm(),09)&Invoke(Fm(),
Fn(),16);
根据推导规则R6:hasSenAction(onClick(),openStream(),NULL,09):-hasSenAction(Fn(),
openStream(),NULL,20)&Invoke(onClick(),Fn(),09);
我们可以得到该应用包含敏感行为(onClick(),openStream(),NULL)。该例中敏感API未
对敏感数据进行操作,所以敏感数据设为NULL。
第五步:对第四步中得到的敏感行为,我们需要将其中UI控件替换为UI上的文本。在
本例的代码片段中,我们可以找到该按钮的id为2131296347,将其转换为16进制数
7F09005B。在第一步中所得layout文件中可以找到该按钮id,并且得到该按钮上的文本为“查
看详细页面”。由此我们得到敏感行为(″查看详细页面″,openStream(),NULL),将其中的API
改为其所属类型,最终得到该应用包含敏感行为(″查看详细页面″,Intemet,NULL)。所举代
码片段情况较为简单,若文本较长或者敏感数据存在,还需作相应处理。
第六步:从第一步中所得的AndroidManifest.xml文件中我们可以得到应用所包含的允许
请求列表,将是否包含某种请求作为应用的特征之一。同时将应用是否包含某种敏感行为作
为应用的特征之一。本例中应用的特征值如下所示。
应用名:wdj
是否包含敏感行为(″查看详细页面″,Intemet,NULL):1
是否包含敏感行为(″确定″,Intemet,UserAccount):1
是否包含敏感行为(″安装″,Install,NULL):1
是否包含敏感行为(″发送″,SendMessage,Message):0
是否包含敏感行为(″同步通讯录″,Internet,AddressBook):l
是否包含允许请求"android.permission.ACCESS_WIFI_STATE":1
是否包含允许请求"android.permission.READ_PHONE_STATE":l
是否包含允许请求"android.permission.ACCESS_NETWORK_STATE":1
是否包含允许请求"android.permission.INTERNET":1
是否包含允许请求"android.permission.GET_ACCOUNTS″:1
是否包含允许请求"android.permission.READ_CONTACTS″:1
是否包含允许请求"android.permission.SENSOR_ENABLE":0
是否包含允许请求"android.permission.READ_SMS″:1
是否包含允许请求"android.permission.RECEIVE_SMS″:1
是否包含允许请求"android.permission.WAKE_LOCK":1
将n个已知安全性的应用进行如上的特征提取后,将它们综合为一个特征矩阵,即可得
到我们所需训练数据集。
第七步:使用支持向量机算法,判断安卓应用的安全性。支持向量机算法首先将向量映
射到一个高维空间,然后再在这个空间中求广义最优分类面。公式如下,
其中ωT用于将向量x映射到高维空间中,向量x为应用的特征向量,(ω)Tx*+b)为通过训练
数据集所找到的最优分类面(x*为满足该超平面的特征向量,由训练结果得出)。f(x)为
应用的安全标签预测值,若f(x)<t,则应用为恶意应用,若f(x)≥t,则应用不是恶意应用。
(t由多组实验结果对比决定,一般情况下将f(x)的值规约到[0,1],t的取值为0.5。)