Page 129 - 《软件学报》2021年第6期
P. 129
张捷 等:基于污染变量关系图的 Android 应用污点分析工具 1703
[3]
泄露情况 [3,10] .污点分析目前广泛应用于 Android 应用的隐私泄露检测,总体上可分为动态和静态两种方法 :动
态方法主要在程序运行过程中对程序的行为进行监控,及时发现隐私数据的泄露,典型的面向 Android 应用的
动态方法有 TaintDroid [11] ,TaintEraser [12] 等;静态方法是在不运行软件的前提下,对隐私数据泄露行为进行分析,
分析的对象可以是源码、中间代码或目标代码等 [13] ,目前比较流行的面向 Android 应用的静态方法有
[8]
[6]
FlowDroid ,Amandroid 等.本文主要研究静态污点分析方法,相比动态方法,静态方法拥有如下优势:(1) 覆盖
全部代码,分析更加全面、准确;(2) 某些恶意应用能够检测出动态分析的运行环境,之后隐藏恶意行为从而逃避
检测,而在静态分析中则不会出现此情况.
下面对污点分析用于隐私泄露检测中的常见概念进行解释.程序中,隐私数据的获取接口被称为污点源
(source).隐私数据的泄露接口被称为泄露点(sink).程序在获取隐私数据之后,可以通过赋值、计算等方式在变量
中对其进行传播,这些变量被称为污染变量(tainted value).污染变量可以是局部变量、静态变量或者对象的域
等.隐私数据从污点源经过污染变量到达泄露点的传播过程形成的数据流可称为污染流(taint flow).图 1 是一个
应用中两个函数的代码片段,图 1(a)中的 onStart 生命周期函数调用了一个污点源 getDeviceID 用于获取设备 ID
号,该隐私数据随后经过 a,b,x,y 等污染变量的传播,到达图 1(b)中 Send 函数的一个泄露点 sendTextMessage,该
API 可将隐私数据通过短信方式进行发送.图中,污染变量用红圈标记,污染流用蓝色实线示意.这条污染流跨越
两个函数,通过赋值、函数参数传递、字符串计算等不同方式进行传播.这些传播方式在污点分析方法中,一般
需要抽象成为污染传播规则用于检测污染变量.
1 onStart( ) 1 void Send(String x)
2 { 2 {
3 a=getDeviceID( ); //source 3 String y=“ID:”+x;
4 String b=a; 4 sendTextMessage(y); //sink
5 Send(b); 5 }
6 }
(a) (b)
Fig.1 An example of inter-procedural taint analysis
图 1 过程间的污点分析示意图
1.2 Android应用污点分析工具实现的关键问题
(1) Android 系统环境的模拟
Android 应用具有事件驱动、多入口、多组件等特点,严格来说,应用不是一个能够独立运行的程序,甚至可
以看作是 Android 操作系统的插件 [14] .应用中没有类似 Java 程序的 main 函数,各组件的生命周期函数或者回调
函数根据用户互动或设备事件触发而由系统环境直接调用,在代码中缺少这些函数之间明确的调用关系.因此,
传统 Java 程序分析工具不能直接使用在 Android 应用上.为了准确分析 Android 应用,我们需要对 Android 系统
环境进行模拟,生成完整准确的函数调用图、控制流图等程序结构.另外,一个 Android 应用可由多个组件构成,
隐私数据可在不同组件间传播,通常将隐私数据封装在用于组件间通信的专用对象 Intent 中,显式或隐式地传
送到另一个组件.因此,Android 应用的污点分析需要获得所有组件间通信信息用于支持组件间分析.目前,研究
人员已经提出一些分析组件间通信的工具,例如 IC3 [15] ,Epicc [16] 等.
(2) APK 文件的反编译
Android 应用的安装文件是 Android 应用程序包(Android application package),文件格式是 APK 文件.该文
件由多个文件组合压缩而成,包含 dex 文件、文件资源、证书、manifest 文件等.其中,与源代码最为相关的是
dex 文件,它是在 Android 的 Dalvik 虚拟机上运行的可执行文件.因为 dex 文件中的字节码不利于直接分析,工具
往往首先将该文件反编译为中间代码(IR)或者源码方便操作.常见工具和中间代码有 Soot [17] 生成的 Jimple、
APKtool 生成的 Smali [18] 、Androguard [19] 生成的 DEX_ASSEMBLER 等等.比较成熟的反编译工具不仅可以生
成中间代码,而且提供在中间代码层面上进行程序分析的操作接口,用于获取程序中的语句、变量等详细信息,
甚至可以直接生成函数调用关系和控制流图等信息.