SmartDroid: an Automatic System for RevealingUI-based Trigger Conditions in Android Applications

文章语言:英文

文章来源:2nd Annual ACM CCS Workshop on Security and Privacy inSmartphones and Mobile Devices (SPSM)-2012CCS workshop汇集

作者信息:

1. Cong Zheng

2. Shixiong Zhu

3. Shuaifu Dai

4. Guofei Gu (简介发表文章汇集)

5. Xiaorui Gong

6. Xinhui Han(简介

7. Wei Zou简介发表文章汇集


发表单位:

  • Beijing Key Laboratory of Internet Security Technology, Peking University
  • Institute of Computer Science and Technology, Peking University

最近几年静态分析和动态分析的演化趋势:

摘要】

UI交互在Android的应用程序中是一种基本的功能,像许多的Activities都需要UI交互来触发。这种类型的UI交互能够帮助恶意软件的apps来隐藏他们的敏感行为(例如:发送短信和获取手机设备的ID号码)通过动态分析工具的检测例如TaintDroid,因为简单的运行app,但是没有正确的UI交互将不会导致敏感行为的暴露。这篇文章关注的就是通过自动的UI交互来触发特定的行为。特别的,通过混合静态分析和动态分析来揭示Android应用程序的基于UI触发的条件。首先使用静态分析来提炼出期望的Activity转换路径通过分析Activity和Function调用图,并且使用动态分析来遍历每一个UI控件并且搜索出UI交互一直到敏感API的路径。作者实现了原型系统SmartDroid并且展示出他能够自动的并且高效的检测出基于UI的触发条件暴露出的敏感行为,使用TaintDroid不能够检测出来的敏感行为。

【设计思路】

Android的Activity是一个屏幕包括了按钮,文本框还有其他的UI元素用来做用户交互。因此,主要的思想就是使用静态分析找出期望的Activity转换路径能够涉及到敏感行为的传播;之后对于每一条路径,我们使用动态分析强迫这个应用程序按照指定的路线运行,直到敏感行为被触发。在动态分析中,SmartDroid将会尝试着和每一个UI元素进行自动的交互通过遍历当前的Activity中的view tree,将APK运行在在修改后的Android系统中。

如果目前的Activity能够跳转到下一个Activity的转换路径,则目前的UI元素就是我们期待的元素将会被保存下来。当遍历到最后一个Activity的时候敏感行为将会被触发。最后,这一系列的UI元素将会被作为触发条件,包括他的坐标以及UI的事件类型。

简要归纳为一下几点:

1.静态分析,找出每个activity之间的调用关系

2.HOOK了framework中的敏感APIs

3.Activity的代码,修改了了startActivity 以及startActivityForResult保证了Activity的跳转是按照想要的路径来转化的。

4.修改了View 之类的含有UI事件的源代码

【概述】

文章使用了Horoscope这个例子来做讲解。下载地址https://play.google.com/store/apps/details?id=fr.telemaque.horoscope

这款软件可以显示每天的和每月的运势。它可以连接Internet以及发送IMEI号通过特地的号码通过点击特定的按钮。点击每天运势和每月运势的时候,会在后台有一些行为。一个是发短信,一个是读取IMEI

在这里我们认为读取IMEI号码以及接入网络都是属于敏感行为并且接入网络能够导致隐私泄露。

使用Apktool反编译了这款软件:APKtool的使用方法可以参考:Ubuntu上安装apktool

基本命令是: apktool d yourapk.apk

这个软件的权限由下列出:

 <uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-feature android:name="android.hardware.wifi" android:required="false" /><uses-permission android:name="android.permission.READ_PHONE_DATA" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.RESTART_PACKAGES" /><uses-permission android:name="android.permission.GET_ACCOUNTS" /><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="com.android.vending.BILLING" /><uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-feature android:name="android.hardware.location" android:required="false" /><uses-feature android:name="android.hardware.location.network" android:required="false" /><permission android:name="fr.telemaque.horoscope.permission.C2D_MESSAGE" android:protectionLevel="signature" /><uses-permission android:name="fr.telemaque.horoscope.permission.C2D_MESSAGE" /><uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

提取出这个软件的所有权限的方法如下,当然和这篇论文是没有关系的,只是想写代码而已~

#!/usr/bin/env python
# coding=utf-8"""
@ AUTHOR   : Chicho
@ VERSION  : 1.0
@ DATE     : 2014-03-23
@ FUNCTION : Get the permission in AndroidManifest.xml
@ FILENAME : getpermission.py
@ COMMAND  : python getpermission.py -d your_directory_store_APKfile
"""import sys, getopt
from xml.dom import minidomif __name__ == '__main__':_directory = ""   # define a directory to store you target file # opts store the relevant parameters , args stores some char except parametersopts,args = getopt.getopt(sys.argv[1:], "d:h", "directory=help")# get the directory for op,value in opts:if op in ("-d", "--directory"):_directory = valuexmldoc = minidom.parse(_directory + '/AndroidManifest.xml')# get all the elements in the manifestmanifest = xmldoc.getElementsByTagName('manifest')[0]permission_list = manifest.getElementsByTagName('uses-permission')#print permission_list#the total number of all the permissionslens = len(permission_list)for i in range(0, lens):permission = manifest.getElementsByTagName('uses-permission')[i]permission_name = permission.getAttribute('android:name')print permission_name

说明:这个软件目前不支持在中国下载,所以下载的和文章的有点不一样,使用的是360手机助手里下载的,还有一个问题,这个软件可以在手机中正常运行,但是在模拟器上跑不起来。
目前还没有分析这个原因,之后会在研究。如果您已经知道了原因可以告诉我,十分感谢。

当这个Horoscope启动的时候Android系统将会创建一个app 的main Activity实例如图1所示。暂停三秒钟之后启动第二个Activity如图1(b)使用了Intent来启动。在这里有两个按钮,是用来登陆FaceBook和Twitter还有其他的按钮是用来设置你自己的生日的。有12个按钮呈现出了不同的星座。当你点击12个图标中的一个图标的时候将会得到一个如图(C)所示的Activity。有两个按钮分别得到每天的还有没月的运程。当你点击两者中的任何一个的时候,它将会跳转到图1中的(d)在最后一个Activity中它可以跳转到如图1(d)中所示的Activity。在最后一个Activity中,它会读取并且发送设备的敏感APIs到远程服务器通过敏感APIs“android.telephony.TelephonyManager.getDeviceId()”以及“org.apache.http.client.HttpClient.execute()”

图2展示出了该架构的原理图,它由FCG(Function Call Graph)函数调用图和ACG(Activity Call Graph)调用图组成。在FCG中,我们可以决定所有的函数调用敏感APIs的路径。开始的路径被定义为敏感源函数。在ACG中,我们定义和敏感函数相关联的Activity叫做敏感池Activity(sensitive sink Activity).例如在图2中,Activity F它联系了两种作为敏感源函数,当目前的Activity跳转到我的ActivityF的时候它将会调用“onCreate()”函数来启动我的ActivityF。之后的控制流程序将会沿着函数调用图到达我的“getDeviceId()” API。于此同时,在Activity F中的按钮点击之后将会调用相应的onClick()函数。这个控制流就会执行“sendTextMessage()” API来发送一条SMS 短信。

我们的方法包括两部,金泰分析阶段以及动态分析阶段。在静态分析阶段能够产生我们期待的Activity路径转换并且用来指导动态分析觉得和哪一个Activity做交互。在动态分析阶段我们可以发现一系列的UI elements能够导致敏感APIs执行。这个UI元素相应的坐标以及事件类型是我们是触发条件。

在静态分析中我们首先使用FCG和ACG,我们必须要分析所有的Intents在调用“startActivity”以及“startActivityForResult”功能来获得源Activity和目标Activity它们之间通过Intent相连接。最终,我们提取出期待的Activity转换路径即从源Activity到每一个敏感池Activity。这个过程包括

(1)     获取所有的敏感函数。我们在FCG当中提取出每一个函数调用敏感API,在每一条路径的第一个first function是源function。

(2)    获取每一个敏感池Activity我们分析这些敏感源Activity是属于哪一个Activity的.

(3)    得到期望的Activity转换路径。我们在ACG当中使用深度优先遍历算法得到路径。

在动态分析阶段我们的目标是判定哪一个UI元素能够触发敏感行为。在知道了期望的Activity路径之后,目标转移的Activity知道哪一个UI可以让应用程序按照期待的Activity路径转换。我们修改了Android系统以至于我们能够遍历并且和UI进行自动的交互从一个Activity到另一个Activity。除此之外我们强迫这个运用程序能够按照期待的Activity转换路径进行,我们限制了Activity的产生通过修改Android系统。如果我们的系统和错的UI元素交互让这个运用程序转换到错误的Activity,我们将会禁止这个错误的Activity产生。最终,当这个敏感行为被触发,我们获得了一系列的UI元素。在和UI交互的时候,我们记录下来他们相应的UI坐标和UI事件类型作为UI触发的基本条件。

【系统设计】

在图3中揭示了SmartDroid系统的概况。他有两个关键部分组成:静态分析路径提取 以及动态UI触发。静态分析选择器用来选择被期待的转换路径能够导致敏感行为的触发。动态UI触发能够根据揭示触发条件和相应的UI元素进行交互得到期待的转换路径。

【静态分析选择器】

静态路径选择器被用来找到正确的Activity转换路径。如果一个应用程序能够按照期待的Activity调用路径运行,他有可能触发敏感行为,否则他是不可能触发敏感行为的。例如,在图2中,我们点击了按钮A这个时候Main Activity将会跳转到Activity A。第一步在这个案例中是错误的,所以不可能触发发送短信这个敏感行为。因此在静态分析中有三部:

反编译,构建FCG和ACG。

下面是由python编写的获取这个软件的包名,以及所有的Activity的方式

当然这篇论文的技术远不止这些,你必须要构建的是他们之间的调用关系,然后构建出他们之间的ACG,这个之间的连接就是我们的Intent

#!/usr/bin/env python
# coding=utf-8
#filename : parseManifest.py
#author : Chicho
#date : 2014-03-23"""
@FUNCTION: 1. Get the package name of you APK2. Get all the activities in you application@VERSION: 1.0
"""
import sys, getopt
from xml.dom import minidom
if __name__ == '__main__':_directory = ""opts, args = getopt.getopt(sys.argv[1:],"d:h","directory=help")for op, value in opts:if op in ("-d", "--directory"):_directory = valuexmldoc = minidom.parse(_directory + '/AndroidManifest.xml')manifest = xmldoc.getElementsByTagName('manifest')[0]package = manifest.getAttribute('package')output = open(_directory + '/package.txt', 'w')output.write(package)output.close()activity_list = manifest.getElementsByTagName('activity')total = len(activity_list)activity_name = ""output = open(_directory + '/activity.txt', 'w')for i in range(0, 38):activity = manifest.getElementsByTagName('activity')[i] activity_name = activity.getAttribute('android:name')print activity_nameoutput.write(activity_name)output.write('\n')output.close()

【反汇编】

对于一个APP,我们想知道哪一个可能的敏感行为,所以我们必须检测这个应用程序中使用的APP。为了实现这个,我们必须要反汇编这个应用程序。考虑到Dalvik bytecode-to-Java bytecode 翻译的准确性。我们更喜欢操作并且分析Dalvik字节码。这个smali code作为Dalvik字节码的中间表现。Smali code 是十分方便的相对分析 Dalvik 字节码。

【构建FCG】

在这一步当中,我们想要发现FCG,在这里,所有的孩子节点都是敏感的API。所以我们第一步是发现所有的敏感APIs的smali代码。在smali代码中我们很容易的知道函数之间的调用关系。我们之后使用交互算法来找到所有的敏感的APIs的调用路径。 但是有很多间接的调用指令以及事件驱动调用也是不能忽视的。实际上一些间接的调用指令来自于Java的多态。我们使用的方法是用Woodpecker的解决方案来解决的。他增加语义事件驱动最终获得了全部的FCG。

【构造ACG】

基于文章介绍的方法是应该完全知道全部的ACG。在Android系统中,Activity是通过Intent的,它是一个消息指明了收件人和可选的数据,并且用它来开启一个新的组件。通常一个Activity开启一个新的Activity它将会创建一个Intent并且调用“startActivity”或者是“startActivityForResult”函数。一般情况下,开发者创建一个“startActivity”或者是“startActivityForResult”调用指令。App将会使用Intents和一个或者其他的应用程序进行交互。除此之外,系统使用Intents作为一个应用程序的通知。我们的目标就是发现所有的Intents并且分析他们的源Activity以及目标Activity通过这些Intents.我们首先介绍Android的Intent之后我们介绍使用这个Intent来做分析的方法。

在Android中有两种类型的Intents:显示的Intent和隐式的Intent。一个显示的Intent能够明确的指出他的接受组件的名字,但是隐式的Activity就只申明了Action。实际上接受者是根据声明在AndroidManifest.xml内容决定的。在AndroidManifest.xml中,所有的组件(包括i.e.Activity,Receiver)在应用程序中定义的他们都能收到特定的actions.

对于一个显示声明的Intent,是十分容易的知道他的目标Activity根据他的定义。但是对于一个隐式的Activity,我们就需要匹配在AndroidManifest.xml中的actions。如果没有匹配的Intent,我们就认为Intent仅仅只能接收系统的组件(i.e.,sms box, email)或者是其他的应用程序。以下列出了6种类型的结构体来构造Intent的对象。

a) Intent()

b) Intent(Intent o)

c) Intent(String action)

d) Intent(String action, Uri uri)

e) Intent(Context packageContext,Class<?>cls)

f) Intent(String action, Uri uri, ContextpackageContext,Class<?>cls)

在构造器a)中,他初始化的是一个null的Intent。之后,可以使用setClass(),setComponent(),setAction()方法来定义目标Activity或者绑定一个目标Activity。c),d),e),f)是等效的。在构造体当中Intent是由其他的Intent产生的,这个时候我们就需要分析更多的参数。构造器c),d)他们是隐式的Intent。可以分析AndroidManifest.xml我们可以决定会启动的Activity根据actions。在e)和f)当中我们显示的声明了Intent所以可以很清楚的知道他的目标Activity是谁。有时在e)中参数“packageContext”就是目前的Activity的名字,所以我们可以很好的获得要启动的Activity,也就是Activity。

在这里举一个例子说明Activity之间的跳转关系,现在有一个比较简单的APK ,主Activity启动secondActivity,在这里使用的是隐式申明:

MainActivity的代码

package com.example.actionattr;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;public class MainActivity extends Activity {public final static String INTENT_ACTION= "net.chicho.intent.action.INTENT_ACTION";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Button bn = (Button)findViewById(R.id.bn);bn.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubIntent intent = new Intent();intent.setAction(MainActivity.INTENT_ACTION);startActivity(intent);}});}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}

second中的代码:

package com.example.actionattr;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;public class SecondActivity extends Activity {protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.second);EditText show = (EditText)findViewById(R.id.ed);String action = getIntent().getAction();show.setText("Action为:" + action);}}

AndroidManifest.xml中的代码

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.actionattr"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="17" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name="com.example.actionattr.MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name="com.example.actionattr.SecondActivity"android:label="@string/app_name" ><intent-filter><action android:name="net.chicho.intent.action.INTENT_ACTION" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></activity></application></manifest>

在这里我们主要的关注是secondActivity中的Action属性。在这里就可以很明确的确定他们之间的调用关系:

<intent-filter>
                <action android:name="net.chicho.intent.action.INTENT_ACTION" />
                 <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>

看马上MainActivity中声明的action

public final static String INTENT_ACTION= "net.chicho.intent.action.INTENT_ACTION";

Intent就好比之间的暗号一样的

Intent intent = new Intent();
  intent.setAction(MainActivity.INTENT_ACTION);
  startActivity(intent);
在来看一下smali代码是什么情况,大同小异:

由于在ManiActivity中实现了匿名内部类,所以出现了上面这个图片的情况。但是在smali代码中仍然是很好找出其中的对应关系

# static fields
.field public static final INTENT_ACTION:Ljava/lang/String; = "net.chicho.intent.action.INTENT_ACTION"
invoke-direct {v1, p0}, Lcom/example/actionattr/MainActivity$1;-><init>(Lcom/example/actionattr/MainActivity;)Vinvoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V
    .line 27.local v0, intent:Landroid/content/Intent;const-string v1, "net.chicho.intent.action.INTENT_ACTION"invoke-virtual {v0, v1}, Landroid/content/Intent;->setAction(Ljava/lang/String;)Landroid/content/Intent;
 .line 18.local v1, show:Landroid/widget/EditText;invoke-virtual {p0}, Lcom/example/actionattr/SecondActivity;->getIntent()Landroid/content/Intent;

这样代码实现的思路应该是很清晰了吧~

【动态UI触发】

动态分析有三个组件:UI交互模拟,Activity限制以及运行时环境。

【运行时环境】

修改了源码的framework层之后在敏感APIs中插入输出日志,便于监控敏感API是否被调用。

【UI交互模拟】

为了让我们的动态分析自动化,我们第一部就是应该开发UI交互模拟器来和UI元素自动的交互。执行UI交互的思想就是:修改Android的framework层的Activity代码,是的可能被遍历的UI元素都被HOOKActivity被组织成一个hierarchy树。View对象是Activity的根节点。我们使用深度优先遍历算法得到每一个UI元素的信息。当遍历到UI元素的时候我们可以触发一些事件监听器。这些事件监听器都涉及到可能的传播路径。在期间我们记录下这个控件的尺寸和坐标。

【Activity限制器】

目前的关键问题就是知道哪一个UI控件的交互会条跳转到正确的Activity,跳转错误的时候就限制其的跳转,这个时候在选择跳转下一个Activity。

转载注明出处:http://blog.csdn.net/chichoxian/article/details/21344357谢谢合作~

SmartDroid论文阅读相关推荐

  1. 论文阅读工具ReadPaper

    对于搞科研的同学们来说,看论文是要经历的第一关,尤其是要读好多篇论文的时候,更是着实令人头大. 这不,最近无意中发现了个在线论文阅读网站:readpaper.com,号称「论文阅读笔记神器,硕博科研学 ...

  2. 多目标跟踪:CVPR2019论文阅读

    多目标跟踪:CVPR2019论文阅读 Robust Multi-Modality Multi-Object Tracking 论文链接:https://arxiv.org/abs/1909.03850 ...

  3. 快速人体姿态估计:CVPR2019论文阅读

    快速人体姿态估计:CVPR2019论文阅读 Fast Human Pose Estimation 论文链接: http://openaccess.thecvf.com/content_CVPR_201 ...

  4. Action4D:人群和杂物中的在线动作识别:CVPR209论文阅读

    Action4D:人群和杂物中的在线动作识别:CVPR209论文阅读 Action4D: Online Action Recognition in the Crowd and Clutter 论文链接 ...

  5. 深度学习点云语义分割:CVPR2019论文阅读

    深度学习点云语义分割:CVPR2019论文阅读 Point Cloud Oversegmentation with Graph-Structured Deep Metric Learning 摘要 本 ...

  6. 3D目标检测论文阅读多角度解析

    3D目标检测论文阅读多角度解析 一.前言 CNN(convolutional neural network)在目标检测中大放异彩,R-CNN系列,YOLO,SSD各类优秀的方法层出不穷在2D图像的目标 ...

  7. 3D目标检测论文阅读摘要

    3D目标检测论文阅读摘要 2D Object Detection 的研究已经非常成熟了,代表作品有RPN系列的FasterRCNN,One Shot系列的YOLOv1-YOLOv3,这里推荐一个2D ...

  8. 目标检测——Faster R-CNN论文阅读

    论文阅读--Faster R-CNN:Towards Real-Time Object Detection with Region Proposal Networks 文章目录 论文阅读--Faste ...

  9. 【独家】深度学习论文阅读路线图

    如果你是深度学习领域的一名新手,可能会遇到的第一个问题是"应该从哪篇论文开始读起呢?" 这里给出了深度学习论文阅读路线图! 路线图按照下面四个准则构建而成: 从提纲到细节 从经典到 ...

最新文章

  1. 【iOS】Xcode 使用 CocoaPods 导入第三方库后没有提示
  2. 神经网络架构演进史:全面回顾从LeNet5到ENet十余种架构
  3. 【HibernateHibernate实体关系映射——双边的多对一、一对多关系
  4. Pycharm / IDEA 局部搜索功能,调试时搜索变量值,或是搜索文件名等局部搜索方法
  5. iPhone至少还要三年才能使用苹果自研5G调制解调器
  6. 华为Mate 30 Pro相机要上天了:主摄或达8100万像素
  7. 编写绘图代码的技巧(二)
  8. Android、Java超详细的身份证验证工具
  9. opengl交叉编译
  10. Android Studio问题解决:Location specified by ndk.dir () did not contain a valid NDK and so couldn‘t sati
  11. 轴承后缀ce和ca_SKF各类型轴承后缀含义
  12. Kettle之Excel输入的简单使用
  13. 同方知网软件_【技巧】方格网土方计算应用技巧,值得学习!
  14. 相对丰度会歪曲实际丰度,联合16S扩增子测序和总菌qPCR获得的绝对丰度可靠吗?...
  15. VUCA时代下,创业团队如何提升整体效率?
  16. ios虚拟服务器降级,升级了iOS 12很后悔,没关系手把手教你如何降级!
  17. 【论文翻译】转移学习推断跨异构网络的社会联系
  18. 文献阅读07期:智网中动态电价对太阳能板普及的影响
  19. ECCV 2020 语义分割论文大盘点(38篇论文)
  20. tta部署_TTA、丰源轮胎云平台项目战略合作交接仪式

热门文章

  1. 系统架构性能问题诊断及优化思路,纯干货!
  2. Java新手,强烈不建议你用 a.equals(b) 判断对象相等!
  3. 面试必问:InnoDB 中一棵 B+ 树能存多少行数据?
  4. 程序员抱怨老婆追王一博入魔,长期被冷落想离婚
  5. 一篇能涨薪水的JVM调优,分析文章
  6. 菜鸟实时数仓技术架构演进
  7. 新晋技术Leader每天996,CTO却给他绩效打C,留下一句话...
  8. 锅都不敢背,凭什么让大家跟着你干?
  9. 怎么用leangoo做需求管理?(用户故事地图)
  10. 分享:Svg文件转换为图片(调用 Inkscape 命令行)