APP下载

基于smali注入的敏感API拦截方法研究∗

2018-11-28朱旭超

计算机与数字工程 2018年11期
关键词:调用日志实例

朱旭超 徐 建

(南京理工大学计算机科学与工程学院 南京 210094)

1 引言

随着移动互联网和移动智能终端的普及和快速发展,移动应用程序的数量呈爆发式增长,其中Android平台智能终端及其应用占据市场主导地位。然而,面对日益增长的应用市场,App被盗版后加入恶意代码的情况越来越严重,部分破坏者利用这些恶意程序收集用户隐私、篡改数据,给用户带来巨大的经济利益损失及安全威胁。攻击者为了更广泛地传播Android恶意应用,会将恶意代码注入并重打包到当前市场上流行的Android应用程序中,并通过第三方电子市场、Android应用程序分享论坛等途径进行传播[9]。

由于Android[15]系统的权限控制机制,用户往往在不知道Apk应用具体需要哪些权限时,在使用Apk前就需要对Apk所需要的权限进行授权。这往往给了恶意应用以可趁之机,通过申请文件读写,短信读写等敏感权限,盗取用户信息[10]。

目前,对于Android平台的安全保护主要有代码混淆,安全加固,权限控制三个方面。目前的权限控制基本是通过第三方应用,如Jinseong Jeon等提出的 Dr.Android[2]以及 Michael Backes等提出的AppGuard[4]等。这些第三方应用往往需要获取ROOT权限,通过广播监听等方式,对于敏感权限进行监控和拦截。然而获取ROOT权限往往会对用户手机的安全性能造成隐藏危害,比如信息泄露风险,系统危害,软件危害等。此外,有些权限控制方面的研究通过修改安卓内核,在内核中加入监听模块从而实现权限控制的效果。如Xueqiang Wang等提出的DeepDroid[3]和Stephen Smalley提出的SE⁃Droid[1]等。这些方案都需要对用户的Android的系统进行一定程度上的修改,而这往往具有很大的风险,会降低系统的稳定性,同时具有较高门槛,普及难度较大[12]。

针对存在的问题,本文提出一种基于smali注入的敏感 API拦截方法研究,通过 smali[5]注入的方式,对程序源代码进行一些修改,并分析敏感权限,映射出对应的敏感API,通过对系统中的敏感API进行拦截,从而实现在不需要ROOT的情况下,在Apk运行中对敏感权限的提醒和拦截的功能。

2 基于smali注入的拦截方法

2.1 处理流程

Dalvik虚拟机是Android系统框架的核心组成部分之一,Android系统实际上很大部分是由java语言编写的。Android软件安装包Apk文件,本质上是一种zip压缩文件,其核心文件是classes.dex。dex文件由该android应用对应工程中所有的java类编译生成的。由于一般无法获得一个android应用的源代码,因此可以利用工具对dex文件进行反编译,获得dalvikbytecode文件,即smali文件,从而实现权限的拦截注入。

具体过程如图1所示,主要分为四个部分:首先确认敏感权限,通过Pscout构造敏感权限-API映射表;然后获取dex文件,使用baksmali工具将dex文件转化为smali文件;接着通过映射表定位敏感API位置,针对smali文件中三类方法调用注入拦截模块,最后使用smali工具将修改过的smali文件还原为dex文件并重打包,签名。

图1 敏感API拦截系统基本流程

2.2 敏感权限-API映射

首先,进行权限拦截前,需要先确认想要拦截的相关敏感权限。在Android中,权限模型是嵌入在Android框架中的,该框架公开了一个应用程序编程接口(API),其中包含用于开发人员与系统资源交互的类和方法。如果调用了某个API,这个API方法涉及到隐私或安全性问题,这个时候框架会检查调用者是否被明确地授予了相应的权限[7]。所以说权限模型对应用程序的开发过程造成了影响,因为开发者必须为其所使用的每一个API申请使程序正常工作的权限。

对于敏感权限拦截来说,需要拦截特定的API,因此需要建立“权限-API”映射关系。然而,由于Android平台的开放性,并且官方总是不给出最新的、清晰的映射关系,开发者经常为了方便而过多地申请权限[14],而Android又缺乏权威机构做规范检查,这使得Android平台冗余授权的现象普遍存在[11]。总的来说,建立Android系统中权限和API清晰明确的映射关系是必不可少的。

“权限-API”映射关系管理模块需要建立“权限-API”的映射关系[13],还需要提供一些其他的辅助功能,例如检索功能,包括根据API检索其需要申请的权限、根据权限检索该需要该权限对应的API。

具体的实现方式:1)通过查看Android官方文档,从中筛选出特定的敏感权限,如android.tele⁃phony.SmsManager为短信收发相关权限,可以将其认定为敏感权限;2)构造“权限-API”之间映射关系,构造过程可以查看Android官方文档,还可以进行动态测试等方法,主要参考现有的PScout工具,构建权限和API之间多对多的映射关系,大致流程如图2所示;3)将映射关系存储到数据库,构建敏感API表;4)实现根据权限检索API、根据API检索权限的功能。

图2 PScout映射构建流程

2.3 API拦截模块

2.3.1 Dalvikbytecode层原方法修改

由于要从dalvikbytecode层通过smali注入[8]的方式,对敏感权限映射的API进行拦截,因此就需要掌握dalvikbytecode方法调用原理。Dalvikbyte⁃code主要有三种类型的调用方法:静态方法,实例方法和构造方法,分别以invoke-static,invoke-vir⁃tual,invoke-direct等三个smali引用关键字开始。不同的调用方法拦截方法不尽相同。

1)静态方法:使用static关键字进行修饰,被调用时必须与类名一起调用,而无需创建对应实例。对于这种静态方法,可以在拦截类中创建一个同名,且同返回类型的方法。比如对于一条静态方法调用smali语句:invoke-static{v0,p0},Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I,要拦截android.util.log.d这一方法,可以在拦截类nde⁃fend中构造一个ndefend.android.util.log.d的方法。这个新方法的参数和返回值与原方法相同。

2)实例方法:实例方法与静态方法不同,实例方法在调用前必须要创建对应的实例对象,使用“对象名·方法名”的方式进行调用。对于实例方法,可以在拦截类中创建一个同名,同返回类型的方法,但是在传递的参数方面,新方法会接受一个被拦截类的实例的一个新参数。比如对于一条实例方法调用 smali语句:invoke-virtual{v6,v7},Landroid/widget/EditText;->setEnabled(Z)V,要拦截android.widget.EditText.setEnabled这一方法,可以在拦截类ndefend中构造一个ndenfed.android.widget.EditText.setEnabled的新方法,但是与原方法不同的地方在于,新方法接收的参数除了原本的boolean型参数外,还要额外接收一个android.wid⁃get.EditText的实例。

3)构造方法:构造方法用来创建类的实例。构造方法没有返回值,对于构造方法来说,一般不涉及敏感API,因此一般不需要进行拦截。对于少数需要拦截的构造方法,可以使用构造一个“工厂”类型的新方法的方式进行拦截。比如一条构造方法调用smali语句:invoke-direct{p0},Landroid/app/Activity;-><init>()V,要拦截 android.app.Activity的构造方法。与之前类似,可以在拦截类ndefend中构造一个ndenfend.android.app.Activity的方法,新方法与原方法有一样的参数,但是返回值为an⁃droid.app.Activity。

针对上述三种调用方法,通过构造对应的新方法来对原方法进行替换,使程序在运行时调用构造的新方法而不是原方法。并且在新方法中,通过反射方式,实现原方法本身的功能,并在其基础上,加入日志记录模块以及权限拦截模块,如图3所示。

图3 构造新方法结构

2.3.2 日志记录模块及拦截模块实现

日志记录模块及拦截模块是通过smali注入的方式来实现的。之前的smali注入就是在软件源代码中添加几行代码,目的在于简单地改变软件功能,或查看修改运行中的某几个寄存器的数值。然而在smali注入时需要注意,添加的注入代码所使用的寄存器不能重复,否则影响后续代码的执行。因此,当注入代码较多时,这个要求就很难实现了。为了解决这个问题,可以把需要注入的日志记录和权限拦截的smali代码写进专门的smali文件,然后在要注入的地方调用smali里预先记录的方法即可,这样我们只用在源代码中注入一行代码,并且不会影响其他寄存器的使用。

例如对于一段简单的smali代码,如图4所示,如果想要对v1,v2两个寄存器进行日志记录,一般使用log.d的smali注入方式,如图5所示。可以看出,这不光需要对代码进行插入,还需要对寄存器个数等全局参数进行修改。

图4 smali注入前代码

当要注入多个模块进行修改时,这种注入方式不仅变更工作量大,而且由于寄存器个数限制等原因,容易造成源程序崩溃,注入失败。因此,可以预先创建crack.smali文件,通过调用创建好的smali文件进行注入。如图6所示就是一个简单的日志记录smali代码:

图5 smali注入后代码

图6 日志记录smali代码

只需要将这样一段smali模块代码放入原安卓应用安装包中,然后在源程序中进行调用即可,这最大限度地减小了需要注入的代码长度,同时不会影响源代码的运行,如图7所示,只要插入一行语句即可,同时不需要对寄存器等全局参数进行修改:

图7 改进后的smali注入后代码

3 测试验证

为了验证日志及拦截模块效果,构造测试用例以测试模块效果。为了易于验证,设计了一款模拟收发短信的安卓应用。该应用通过调用系统的SMSManager等敏感API,可以实现与系统自带信息相类似的收发短信的功能。程序由Java实现,敏感API日志记录以txt形式保存在手机本地sd卡中。

运行njust.defend.java注入模块,模块首先调用baksmali工具,将Apk文件中的classes.dex文件转化为classes对应的smalli文件。将事先编译好的LogRecord.smali和Intercept.smali放入classes.dex文件夹,接着对该文件夹下所有的smali文件进行遍历,对于其中的API调用函数,逐条与敏感API数据库相比对,确定需要替换的敏感API,并构建对应新的API调用方法。

将修改过后的smali文件重新转化为dex文件并重打包签名后的app安装到手机上,运行时结果如图8所示,会跳出与用户交互的可选择弹窗,即可提醒用户应用在调用的敏感权限,即获取用户手机号码,由用户选择是否允许该行为。同时也会在手机本地生成Log.txt的日志文件,如图9所示。

图8 用户交互权限控制弹窗

图9 log日志文件

4 结语

为解决在不ROOT且不加装第三方应用的情况下对android手机应用进行权限防护,本文利用Pscout,baksmali和 smali等工具,设计并实现了一种基于smali注入的android手机应用敏感权限日志记录和拦截的相关模块。实验以正常短信发送程序被注入恶意短信拦截smali代码为例,进行smali代码注入的实验,成功打印并拦截到短信收发、号码读取等敏感权限。但是该方法也存在一定的不足,对于一些进行过加固的Apk,通过反编译得到的smali文件往往有缺失,因此难以使用smali代码注入的,这也是smali代码注入的一个局限性。对于这种情况,可以选择结合现有的一些脱壳的手段对smali文件进行还原再进行smali注入。

猜你喜欢

调用日志实例
一名老党员的工作日志
扶贫日志
核电项目物项调用管理的应用研究
系统虚拟化环境下客户机系统调用信息捕获与分析①
雅皮的心情日志
雅皮的心情日志
完形填空Ⅱ
完形填空Ⅰ
利用RFC技术实现SAP系统接口通信
C++语言中函数参数传递方式剖析