一种Android应用的模糊测试方法及系统与流程

文档序号:11829383阅读:220来源:国知局
一种Android应用的模糊测试方法及系统与流程

本发明涉及软件自动化测试领域,尤其涉及一种Android应用的模糊测试方法及系统。



背景技术:

目前,对Android应用进行自动化测试主要集中在针对应用界面操作功能的测试上,即对用户的动作输入进行测试。然而现有的测试方式忽略了对用户另一块输入—外部数据输入的测试。外部数据输入是指Android应用声明的、能够在应用中处理的外部数据。Android系统提供了一套机制以方便应用接收外部数据输入。外部数据输入作为不可控的外界输入,经常会触发应用软件中的缺陷,所以对其进行测试以进一步挖掘应用程序的漏洞非常有必要。

因此,现有技术还有待于改进和发展。



技术实现要素:

鉴于上述现有技术的不足,本发明的目的在于提供一种Android应用的模糊测试方法及系统,旨在解决现有的应用测试方法缺少外部数据输入测试的问题。

本发明的技术方案如下:

一种Android应用的模糊测试方法,其中,包括步骤:

A、预先在应用的配置文件中声明每一活动组件的过滤器;

B、利用模糊测试技术对输入的外部数据进行模糊变异,以生成测试用例数据;

C、将测试用例数据发送到应用的活动组件,然后通过虚拟机层和native层动态监测应用的运行过程。

所述的Android应用的模糊测试方法,其中,所述步骤A具体包括:

A1、预先构造Intent对象;

A2、在应用的配置文件中声明每一活动组件的过滤器;

A3、将应用的每一活动组件和相应过滤器中的<data>数据绑定。

所述的Android应用的模糊测试方法,其中,所述步骤B具体包括:

B1、在外部数据的树形结构中遍历每个数据单元中的任一基本元数据;

B2、依据基本元数据的类型和大小替换基本元数据的初始值,以生成测试用例数据。

所述的Android应用的模糊测试方法,其中,所述步骤C具体包括:

C1、自定义活动组件的监听器,将监听器注册到系统服务中,通过监听器监听活动组件的生命周期异常;

C2、通过监控用于转储内存映像和调试信息的系统文件夹的变化情况来实现对Native层的监测。

所述的Android应用的模糊测试方法,其中,所述基本元数据包括整型、标志、字符串和字节数组。

所述的Android应用的模糊测试方法,其中,所述步骤C2具体包括:

C21、在Native层,添加Java层在Native层对应的底层函数名称和当前系统调用接口名称以及与当前UI相关的活动组件名称;

C22、若发生崩溃的Native层与UI有关,则记录与当前UI对应的活动组件名称;

C23、根据活动组件的名称获取对应的data数据,从而准确定位native层出错信息。

一种Android应用的模糊测试系统,其中,包括:

预处理模块,用于预先在应用的配置文件中声明每一活动组件的过滤器;

测试用例数据生成模块,用于利用模糊测试技术对输入的外部数据进行模糊变异,以生成测试用例数据;

动态监测模块,用于将测试用例数据发送到应用的活动组件,然后通过虚拟机层和native层动态监测应用的运行过程。

所述的Android应用的模糊测试系统,其中,所述预处理模块具体包括:

构造单元,用于预先构造Intent对象;

声明单元,用于在应用的配置文件中声明每一活动组件的过滤器;

绑定单元,用于将应用的每一活动组件和相应过滤器中的<data>数据绑定。

所述的Android应用的模糊测试系统,其中,所述测试用例数据生成模块具体包括:

遍历单元,用于在外部数据的树形结构中遍历每个数据单元中的任一基本元数据;

生成单元,用于依据基本元数据的类型和大小替换基本元数据的初始值,以生成测试用例数据。

所述的Android应用的模糊测试系统,其中,所述动态监测模块具体包括:

虚拟机层监测单元,用于自定义活动组件的监听器,将监听器注册到系统服务中,通过监听器监听活动组件的生命周期异常;

Native层监测单元,用于通过监控用于转储内存映像和调试信息的系统文件夹的变化情况来实现对Native层的监测。

有益效果:本发明首先在Android源码基础上修改应用的配置文件相关代码,使应用的每一活动组件均可正确处理获得的外部数据,然后利用模糊测试技术来进行模糊变异,生成测试用例数据,最后通过虚拟机层和Native层进行动态监测,本发明以待测应用为输入,测试结果文件为输出,测试过程无需人工干预,可高效地实现应用的外部数据输入自动化测试。

附图说明

图1为本发明一种Android应用的模糊测试方法较佳实施例的流程图。

图2为图1所示方法中步骤S101的具体流程图。

图3为图1所示方法中步骤S102的具体流程图。

图4为图1所示方法中步骤S103的具体流程图。

图5为图4所示流程中步骤S302的具体流程图。

图6为本发明一种Android应用的模糊测试系统较佳实施例的结构框图图。

图7为图6所示系统中预处理模块的具体结构框图。

图8为图6所示系统中测试用例数据生成模块的具体结构框图。

图9为图6所示系统中动态监测模块的具体结构框图。

具体实施方式

本发明提供一种Android应用的模糊测试方法及系统,为使本发明的目的、技术方案及效果更加清楚、明确,以下对本发明进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。

请参阅图1,图1为本发明一种Android应用的模糊测试方法较佳实施例的流程图,如图所示,其包括步骤:

S101、预先在应用的配置文件中声明每一活动组件的过滤器;

S102、利用模糊测试技术对输入的外部数据进行模糊变异,以生成测试用例数据;

S103、将测试用例数据发送到应用的活动组件,然后通过虚拟机层和native层动态监测应用的运行过程。

Android应用通常包括四大组件:Activity (活动)、Service (服务)、Broadcast Receiver (广播)和 Content Provider (内容提供器)。Activity 是组成应用界面的基础,每个Activity对应于一个完整的应用界面,其具有一系列生命周期函数,Android系统通过维护一个Activity栈实现应用的界面状态保存和界面跳转。由于Activity是用户与应用程序交互的主要接口,同时应用程序的基础功能逻辑都在Activity中实现,所以应用的外部数据输入总是先由Activity接收并处理。通过声明每一Activity的过滤器,使Activity能够正确处理获得的外部数据,然后对外部数据进行模糊变异,生成畸形数据即测试用例数据,最后发送到Activity进行测试。

进一步,如图2所示,所述步骤S101具体包括:

S201、预先构造Intent对象;

S202、在应用的配置文件中声明每一活动组件的过滤器;

S203、将应用的每一活动组件和相应过滤器中的<data>数据绑定。

在对应用进行数据传输时,需要使用由系统构造或由其他应用构造的Intent对象。在Android系统中,Intent对象描述了一个即将执行的操作,该对象中封装了数据和动作,当从外界向一个应用发送构造好的Intent对象时,Intent对象携带的数据则构成输入的外部数据,且能够被该应用处理。

为了能够正确处理Activity获得的外部数据,任何需要获得外部数据的Activity须在应用配置文件中声明相应的过滤器,即Intent-Filter标签,以确定相应Activity可以接受外部数据输入的类型,而没有声明过滤器的Activity则不具备处理外部数据输入的能力。

在一个Activity中,可以声明多个过滤器(即多个Intent-Filter标签),每个过滤器通常由<action>标签、<category>标签和<data>标签组成:<action>标签用于定义该过滤器执行的动作,<category>标签定义了该Activity处理接收到的intent对象时所需的其他一些信息,<data>标签则是和处理外部数据相关的一个重要标签,<data>标签声明了与外部数据相关的信息,主要包括数据URI属性和数据类型属性。

其中,数据URI属性定义了该Activity能够处理的外部数据的URL,固定格式为"scheme://host:port/path",表示只有符合该属性定义的URL才能够被Activity成功识别并接收。数据类型属性用于规定该Activity能够处理的数据类型,所有的Activity能够处理的外部数据类型皆为MIME类型(即多媒体类型),MIME类型主要包括视频、音频、文本和图像等类型。当其他Activity构造符合数据URI属性的路径字符串,并传递符合<data>标签定义的数据类型的外部数据到目标Activity时,即能被成功接收并处理。

每一个Apk(应用安装包)文件都是一个归档文件,它里面包含了Android应用程序的配置文件AndroidManifest.xml。Android系统是通过PackageParser.parseApplication()函数对AndroidManifest.xml文件中的应用标签进行解析,并通过函数PackageManagerService.scanPackageLI()将解析应用得到的package、provider、service、receiver和activity等信息保存在PackageManagerService服务中,PackageManagerService是一个应用程序管理服务,主要负责扫描系统中特定的目录,找到里面的应用程序文件,即以Apk为后缀的文件,然后对这些文件进解析,得到应用程序的相关信息,完成应用程序的安装过程。其中,PackageParser.parseApplication()这个函数定义在frameworks/base/core/java/android/content/pm/PackageParser.java文件中,PackageManagerService.scanPackageLI()这个函数定义在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中。本发明通过修改这两个函数,将解析应用得到的每一个activtiy和其对应的<intent-filter>标签中<data>数据绑定,并保存起来,从而为后续针对每一个Activity的数据构建测试用例做准备。

进一步,如图3所示,所述步骤S102具体包括:

S301、在外部数据的树形结构中遍历每个数据单元中的任一基本元数据;

S302、依据基本元数据的类型和大小替换基本元数据的初始值,以生成测试用例数据。

本发明采用Fuzzing技术(模糊测试)对Android应用进行测试,Fuzzing的数据来源即为应用的外部数据输入,通过分析数据的特征对数据进行统一描述并构建测试用例数据,从而实现对应用输入数据的充分测试。

Fuzzing技术可以对软件进行安全性测试,在测试方法分类中,可归于黑盒测试和灰盒测试领域。其可提供一系列的非预期输入测试系统同时检测是否引发异常结果来发现软件故障。模糊测试一般是自动的或者是半自动的过程,该过程是控制测试目标并反复的为其提供所需处理的数据,观察是否能引发测试目标的未定义的或者不安全的行为。

在前文中描述的过滤器约定了数据传递的方式并声明了所需的数据类型。而在过滤器中能够声明的数据类型为MIME类型。MIME是描述消息内容的一项因特网标准,能够统一多媒体数据在互联网协议中的携带方式。MIME类型一般都有规定严格的数据格式。MIME数据类型虽然可以简单的划分为常见的几大类,但是各类数据中都囊括了若干具体的数据类型,例如MIME数据类型中的视频类就包括了 MP4、AVI、MKV、RM等数十种数据类型。

通过对比不同数据类型发现,MIME数据类型皆采用树形结构描述自己的数据类型。数据类型的树形结构由不同的数据单元组成,数据单元再由一系列具有不同意义的元数据构成。每个数据单元在被程序读取时会被解析成为一个结构体,数据单元中的元数据则被赋值给结构体中的字段,如此,一份完整的MIME数据在程序中将会被解析成具有不同含义的结构体。

树形结构是MIME数据类型的宏观形式,树形结构中的节点即代表了不同的数据单元,数据单元中存储的元数据则代表了 MIME数据类型中真正有意义的数据字段。对于给定的一种MIME数据而言,其数据单元的格式是固定的。

MIME数据类型被以数据单元为单位分割成树的节点(包括叶子节点和非叶子节点),但是对各类不同的MIME数据类型而言,其拥有的数据单元是各不相同的,即使是同一 MIME数据中拥有的若干数据单元在格式也是基本不同的。

所以,任何MIME数据类型皆由若干数目有限的数据单元组成,该数据单元对于特定的MIME数据类型是格式固定的,通过有规律的组合形成数据的树形结构。要对数据单元进行统一描述,则要对数据单元进行进一步的划分,即将数据单元划分到不可再分割的元数据,使得数据单元由若干具有统一特性的元数据组成,进而使用该类元数据对不同的数据单元进行统一描述。通过对不同的数据单元的综合分析,发现组成一个数据单元的元数据基本有如下几种类型:

1)整型:通常用于表示字节长度、ID数值、版本数值、时间戳等,其长度通常为8位的倍数。

2)标志:其取值范围空间比较狭小,在程序中通常用于表示一个枚举值,用于作为判断条件。

3)字符串:其特点是长度可变。

4)字节数组:字节数组可以用于存储一些复杂结构,例如映射图、矩阵等,也可以用来存储大量样本数据。

5)表格:表格在很多数据单元中都会出现,可以用于存储一些重要的数据结构。

6)子节点单元:宏观上可以将节点数据单元视为一个数据单元,并将其内嵌套的子节点数据单元视为一个特殊的“元数据”,然后采用递归的方式对其进行描述。

在上述元数据分类中,整型、标志、字符串和字节数组这四种元数据不可再分,属于基本元数据。表格由基本元数据通过一定规律组成。而对于子节点单元,在很多MIME数据类型中,都会遇到数据单元嵌套问题,即数据单元A中既包括了基本元数据又嵌套了数据单元B作为其数据部分。针对上述情况,可以将被嵌套的数据单元当作子节点单元,宏观上将其当作父节点单元的数据部分,在解析过程中采用递归解析的方式完成数据描述。

如上所述,元数据总共分为六种类型,其中由于表格和子节点元数据在解析过程中会被进一步划分为其余四类基本元数据,因此实质上只需要对这四类基本元数据设计测试用例库即可。

在高级语言中,这四种基本元素类型皆对应于语言中的某个基本数据类型。整型和字符串对应于高级语言中的整型和字符串,标志对应于枚举类型,实质上也是整型的范畴,字节数组对应于高级语言中的数组,并且以字节为单位。本发明采用Fuzzing中值替换的方法生成样本数据的测试用例。其所做的操作为:在树形结构上遍历每个数据单元中的任一基本元数据,依据该基本元数据的类型和大小替换此基本元数据的初始值,以生成畸形数据,该畸形数据即为输出的测试用例数据,可构建测试用例库如下:

整型:基本元数据中的整型被设计为字节的倍数,因此其测试用例主要考虑整数边界值。

标志类型:标志作为枚举值,其值域通常较为狭窄。主要采用对给定字节长度的整型进行某位置1的方法。

字符串:字符串是高级语言中的一种重要类型,用于存储字符常量。字符串的测试用例数据主要考虑字符串是否存在,以及字符串结束符的问题。另外,在高级语言中,字符串常量还有一个重要的作用是作为格式化字符串(或是正则表达式)存在,此时的字符串的一些特殊字符会被代码解析为特定的含义,因此在字符串测试用例数据中还可添加特殊字符的设计。

字节数组:字节数组在很多数据单元中实际上用于存储一块连续数据,例如存储一个矩阵或是映射表等。本发明采用的是使用随机值法生成变异用例。在使用随机值生成变异用例时,还需要限制变异的次数,避免降低效率。

在进行监测时,启动运行待测应用,根据解析出的外部数据输入发送模式构造正确的Intent对象,将测试用例数据发送到相应的Activity中进行处理,同时监测应用在Dalvik虚拟机层和Native层的运行情况,在出现错误时保存出错点信息,生成测试结果。

MIME数据通过变异生成测试用例数据后,该测试用例数据将作为输入进行测试,测试的过程需要实时监测以记录应用是否产生运行时错误。Android应用在系统中运行时,宏观上可以分为两个层次:1)应用的Dex文件中的字节码运行在Dalvik虚拟机中;2)调用应用的.so库代码或上层应用通过JNI方式调用底层库函数时程序运行在Native层中。

Dalvik虚拟机中运行的是Dalvik字节码,该虚拟机拥有一套完整的内存管理、堆栈管理、异常管理等机制支撑应用的字节码运行。当字节码中存在错误引发未捕获异常时,该异常仅限于单个虚拟机,并且引发的问题通常只会导致应用程序无响应或假死,很少会直接导致进程崩馈、系统性异常等严重后果。

在虚拟机中运行的应用当需要调用应用自身封装的.so库函数或是上层框架通过JNI机制调用本地库实现基础功能时,运行状态在Native层。Native层的运行由系统内核统一管理,在Native层发生的异常通常比较致命,会导致当前进程崩溃,或是引发系统性异常等严重后果。

对于虚拟机层的错误监测,通常情况下,一个Android应用代码的主体部分由JAVA语言实现,即Android应用的逻辑功能运行的主要层面在虚拟机层上。

ActivityManagerService是Android系统中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作。分析Android源码,ActivityManagerService由ActivityManagerNative类派生,而ActivityManagerNative由Binder派生,实现了IActivityManager接口。客户端使用ActivityManager类。由于ActivityManagerService是系统核心服务,很多API不能开放供客户端使用。客户端ActivityManager通过一个ActivityManagerProxy对象与ActivityManagerService通信,而ActivityManagerProxy是通过ActivityManagerNative的getDefault函数得到。

通过分析源码可知,ActivityManagerService中预留了public void setActivityController(IActivityController watcher) throws RemoteException函数用于设置对Activity的监听,而在IActivityController类中,定义了以下函数用于对Activity主要生命周期过程的监听,

public boolean activityStarting(android.content.Intent intent, java.lang.String pkg) throws android.os.RemoteException

public boolean activityResuming(java.lang.String pkg) throws android.os.RemoteException

public int appEarlyNotResponding(java.lang.String processName, int pid, java.lang.String annotation) throws android.os.RemoteException

public int appNotResponding(java.lang.String processName, int pid, java.lang.String processStats) throws android.os.RemoteException

public boolean appCrashed(java.lang.String processName, int pid, java.lang.String shortMsg, java.lang.String longMsg, long timeMillis, java.lang.String stackTrace) throws android.os.RemoteException;

因此,本发明通过重写以上函数,在以上函数中记录测试用例数据的流程过程,实现一种自定义的监听器,最后通过将自定义的监听器注册到该系统服务中,就能够监控系统中所有Activity的运行过程。这样,完成了对待测应用Activity动态监控的功能,从而在虚拟机层捕获Activity的异常情况。其中IActivityController位于frameworks/base/core/android/app/IActivityController中。

进一步,如图4所示,所述步骤S103具体包括:

S401、自定义活动组件的监听器,将监听器注册到系统服务中,通过监听器监听活动组件的生命周期异常;

S402、通过监控用于转储内存映像和调试信息的系统文件夹的变化情况来实现对Native层的监测。

虚拟机是连接上层应用与底层核心、本地库的中间媒介,虚拟机中运行的应用发生的错误通常在上层即可检测到,但是当上层应用通过JNI的方式调用底层接口(简称Native层接口)时,也可能产生错误情况。在这种情况下,通过注册Activity监听器的方案无法实现Native层出错的捕获,因此还需要实现一种监测Native层异常的方案获取底层异常错误信息。

对于Native层出错监测,因为Android是基于Linux系统内核开发得到,其底层的实现中保留了Linux系统程序异常退出机制的核心转储过程,因此可采用监测核心转储文件的方法监控Android系统Native层的出错情况。在Android系统中,当Native层出错时,系统会自动将内存映像和调试信息转储到一个名为tombstones的系统文件夹下,因此监控该文件夹下的变化情况能够实现对Native层出错的监测。

如图5所示,所述步骤S302具体包括:

S501、在Native层,添加Java层在Native层对应的底层函数名称和当前系统调用接口名称以及与当前UI相关的活动组件名称;

S502、若发生崩溃的Native层与UI有关,则记录与当前UI对应的活动组件名称;

S503、根据活动组件的名称获取对应的data数据,从而准确定位native层出错信息。

Android 系统中tombstones处理部分的源码位于 /system/core/debuggerd.c 和 bonic/linker/debugger.c 中。而在/system/core/debuggerd中进行crash进程的分析( handle_crashing_process 函数中),生成tombstones文件(dump_crash_report 函数)。当Android系统中应用出现Native崩溃时,会在 /data/tombstones 目录下生成 tombstone_xx 的日志文件,该日志文件只记录了应用crash发生时的内存、寄存器、堆栈信息等。本发明通过修改handle_crashing_process()函数,在Native层添Java层在Native层对应的底层函数名称、当前系统调用接口名称、以及与当前UI相关的活动组件名称,如果发生崩溃的Native层是和当前UI相关,记录当前出错的Activity名称,并根据Activity找出与其对应的meta-data数据,从而准确定位Native层出错信息。

基于上述方法,本发明还提供一种Android应用的模糊测试系统较佳实施例,如图6所示,其包括:

预处理模块100,用于预先在应用的配置文件中声明每一活动组件的过滤器;

测试用例数据生成模块200,用于利用模糊测试技术对输入的外部数据进行模糊变异,以生成测试用例数据;

动态监测模块300,用于将测试用例数据发送到应用的活动组件,然后通过虚拟机层和native层动态监测应用的运行过程。

进一步,如图7所示,所述预处理模块100具体包括:

构造单元110,用于预先构造Intent对象;

声明单元120,用于在应用的配置文件中声明每一活动组件的过滤器;

绑定单元130,用于将应用的每一活动组件和相应过滤器中的<data>数据绑定。

进一步,如图8所示,所述测试用例数据生成模块200具体包括:

遍历单元210,用于在外部数据的树形结构中遍历每个数据单元中的任一基本元数据;

生成单元220,用于依据基本元数据的类型和大小替换基本元数据的初始值,以生成测试用例数据。

进一步,如图9所示,所述动态监测模块300具体包括:

虚拟机层监测单元310,用于自定义活动组件的监听器,将监听器注册到系统服务中,通过监听器监听活动组件的生命周期异常;

Native层监测单元320,用于通过监控用于转储内存映像和调试信息的系统文件夹的变化情况来实现对Native层的监测。

关于上述模块单元的技术细节在前面的方法中已有详述,故不再赘述。

综上所述,本发明首先在Android源码基础上修改应用的配置文件相关代码,使应用的每一活动组件均可正确处理获得的外部数据,然后利用模糊测试技术来进行模糊变异,生成测试用例数据,最后通过虚拟机层和Native层进行动态监测,本发明以待测应用为输入,测试结果文件为输出,测试过程无需人工干预,可高效地实现应用的外部数据输入自动化测试。

应当理解的是,本发明的应用不限于上述的举例,对本领域普通技术人员来说,可以根据上述说明加以改进或变换,所有这些改进和变换都应属于本发明所附权利要求的保护范围。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1