1.DroidRA论文阅读
概述:
DroidRA: taming reflection to support whole-program analysis of Android apps-ISSTA2016
开源代码:https://github.com/serval-snt-uni-lu/DroidRA
常见的安卓静态分析工具,如安卓污点分析工具FlowDroid,在分析时常常忽略了安卓/Java的反射机制(reflection),在分析时若遇到反射调用,因为不知道反射调用的目标值(如目标method、目标field),会导致分析的中断、错误。
DroidRA将反射调用的分析转化为composite constant propagation problem(复合常量的传播问题),利用COAL求解器解决相应的问题,得到反射调用的目标值;然后通过插桩,用指向目标值的普通Java调用替换反射调用。给定原始APK,DroidRA分析、插桩后得到增强后的boost-APK,boost-APK中的反射调用已经替换为普通的Java调用,使FlowDroid等工具可以更准确的进行静态分析。
APK,安卓数据和资源包,文件主要包括: Android Manifest.xml, class.dex (字节码文件, 由 Dalvik 虚拟机解释), 其他二进制或 XML 格式的资源文件都保存在res/和assets/目录下。
Java反射机制,表现为动态获取信息以及动态调用对象的方法。例如: 在运行状态中, 对于任意一个类, 都能够知道这个类的所有属性和方法; 对于任意一个对象, 都能够调用它的任意一个方法和属性。在安卓中,常常用于在运行时确定class或者method是否可用、确定泛型(genericity)等等,如下图的例子,根据运行时b的状态确定method,一般的静态分析不确定b于是无法确定m,于是无法继续分析。
Motivation
一般的安卓静态分析工具,如安卓污点分析工具FlowDroid,无法处理Java反射机制,遇到反射method等等分析就停止了。导致分析的不准确,如图。
5-8行反射调用了setImei() and getImei()两个method以及field;第2行获取了隐私数据,device ID,在第6行进入了field imei,在第8行通过getImei()进入了字符串s,最终在第10行泄露了隐私数据。
FlowDroid等工具无法处理反射调用,也就无法发现这个数据泄露。
DroidRA通过将相关method和field的反射调用,转换成标准的Java调用,然后FlowDroid就可以检测到这个leak。
安卓中的反射调用
uses of reflection
Providing Genericity. 确定泛型的类型,如上图中example1,
Maintaining Backward Compatibility。开发者可能和设备使用者用着不一样的Android version(android sdk),开发者在使用新的class时,需要先确定所在环境是否存在这个class,也就是保持对旧版本安卓的兼容性。如上图example 2.
Reinforcing App Security。使用反射调用,动态加载代码,避免逆行工程,从而保护app的安全。
Accessing Hidden/Internal API。在开发环境,开发者使用android.jar library package提供的SDK API。而有趣的是,在某个平台实际运行时,library提供的API往往会更多(可能是由于某些API只为某个平台设计,或者API仍在开发中等等)
这时候可以用反射调用来使用这些额外的API。如上图example3
reflection pattern总结
作者统计了45种至少包括3个反射调用的,反射模式(pattern)。
下图显示了,使用reflection机制,动态获取method/field的一般模式
DroidRA框架:
DroidRA的框架如下,包括JPM、RAM、BOM三部分。
JPM, Jimple Preprocessing Module。DroidRA的分析和插桩都是基于IR Jimple,故需要将Dex中的Dalvik bytecode转换为Jimple.第一步,反编译apk并输出Jimple;第二步,由于安卓文件没有一个入口点,而后续的反射分析需要一个入口点,故利用FlowDroid使用的方法,生成一个虚拟的main method作为entry point;第三步,递归的解压JAR,寻找dex文件,以备后续的Dynamic Code Loading的分析。
RAM,Reflection Analysis Module。根据COAL的规定,将Java反射调用的method、class等提取为COAL的object,然后利用COAL求解反射调用目标值。例如下图是一个反射调用问题,以及对应的COAL表示,使用COAL solver求解此表示即可得到反射调用目标值。
RAM输出反射分析结果到json。
DroidRA使用的COAL,是基于ICSE2015的工作。
BOM,Booster Module。根据RAM的分析结果,将反射调用对应的标准Java调用语句添加到APP code,同时保留原始的反射调用语句。在动态运行时,仍执行原始的反射调用,从而保证插桩没有改变程序的原始状态;在静态分析时,使用标准的Java调用path,从而生成更完整的CFG、进行更好的静态分析。
如下图,+号是插桩的语句。静态分析时if判断成立,使用增加的标准的Java调用path。而动态执行时,if不成立,使用原始的反射调用语句。
BOM输出结果是插桩后的APK。
Evaluation
RQ1: Coverage of Reflective Calls
发现并确定反射调用target的能力:
RQ2: Comparison with Checker
和一个类似的工具Checker相比,解决了更多的method/constructor
RQ3: Call Graph Construction
通过解决反射调用的target,使得静态分析得到的CG有更多的边。Diff是多出的边。
RQ4: Improvement of Static Analysis
IccTA是FlowDroid的扩展版。
只使用 FlowDroid-IccTA,只识别了一个反射调用相关的隐私泄露leak,而使用DroidRA和FlowDroid-IccTA成功识别到12个leak。
2.DroidRA工具使用
从开源代码,下载、修改、编译即可。例如,使用Intellij IDE,编译DroidRA-master项目。编译后,可以运行整个DroidRA项目。
测试可以使用DroidRA提供的Benchmark Apps,也可以使用FlowDroid的DroidBench的Reflection apps。输入一个apk和相关jar,结果是输出插桩后的apk,以及分析结果的txt、json等等。
更多信息可以阅读源码,从DroidRA-master\src\lu\uni\snt\droidra\Main.java入手。
遇到的两个问题及解决:
1.需要使用JAVA为Jdk1.8,且需要在linux环境下运行,否则DroidRA使用soot时会报错:
Exception in thread "main" java.lang.RuntimeException: This operation requires resolving level SIGNATURES but android\support\v4\content\Loader$ForceLoadContentObserver is at resolving level HIERARCHY
2.若遇到java: cannot find symbol symbol: method builder(java.lang.String)等问题,删除项目,新建项目,重新编译即可。
具体运行:
编译后,DroidRA-master\out\production\DroidRA-master\lu\uni\snt\droidra\Main.class的main()作为整个DroidRA项目的入口,在intellij中,可以右键run Main.main()
注意需要提供环境变量:
apk文件路径,如:/home/erio/IdeaProjects/DroidRA-master/MytestAPPs/Reflection1.apk
apk相关jar路径,如:/home/erio/IdeaProjects/DroidRA-master/MytestAPPs
android frameword 中android.jar的路径,如:/home/erio/IdeaProjects/DroidRA-master/MytestAPPs/android.jar
3.DroidRA与其他分析工具的配合使用
DroidRA与其他工具的配合:使用DroidRA插桩得到的apk进行分析,减少反射调用的影响,FlowDroid等安卓静态分析工具可以得到更好的分析结果。