Android之ICC机制(三)
前言
从v2.8开始,FlowDroid集成ICCTA模块,只要提供指定格式的ICC信息(即ICC model),FlowDroid可以在CallGraph(CG)中增加重定向边,弥补ICC的在CG中的不连续(如下)。本篇文章小结为了让FlowDroid实现ICC插桩,构造尽可能完整且有效的ICC model的过程。
1 | eg. Activity1在onCreate()中调用startActivity(),调起Activity2。 |
获取完整有效的ICC model
方案一:IC3中获取ICC model
FlowDroid中的ICCTA模块以IC3生成的ICC model作为输入样例。所以首先尝试的方法从IC3中获取ICC model。
IC3生成ICC model过程如下:
- step1: 首先通过反编译工具dare获取apk的.class文件。
- step2: 以.class文件作为输入,调用IC3 jar包,配合指定参数生成ICC model。
问题及解决方案
问题一:dare工具老旧,大多数应用反编译阶段就失败了,无法获取.class文件。
使用别人修改过的IC3
github有别人修改过的jar包modified-IC3.jar,只要求输入apk不需要反编译,粗略逆向发现其在源码中也使用了Dex的文件修改库dexLib2对apk做解析,相当于集成了反编译这一步。然而运行modified-IC3.jar生成ICC model, 依旧有些和dare+IC3相同的错误没法生成ICC model。
dex2jar+IC3
另一个思路是,其他反编译工具替换dare生成.class文件,这里使用了d2j-dex2jar。将结果输入到IC3并运行IC3,可以生成ICC model,但得到的ICC model只包含来自AndroidManifest.xml的组件基本信息而不包含ICC 信息字段,或者包含ICC字段信息但输入到FlowDroid中也没有产生重定向边。
问题二:IC3生成的ICC model没有包含有用的ICC 字段信息(exit_points字段)
Flowdroid导出反编译class + IC3
FlowDroid也在github上提供了他们自己用IC3生成的ICC model。对于那些dex2jar+IC3的方法中出现有效ICC model输入到FlowDroid后无法产生重定向边的测试应用,可以在FlowDroid中找到对应的ICC mode,然后输入到FlowDroid中是可以产生重定向边的。比较两个出处的ICC model发现仅有exit_point字段的id值和statement值稍有差异。由于IC3官方文档的网站没有维护,所以对C3的使用和结果解读没有找到清晰的说明,这里通过IC3,ICCTA,FlowDroid等多处提及IC3的github仓库中issue寻找答案。在某个issue中提到“id”表示调用ICC 方法的指令位置,statement表示ICC方法(记录的应该是jimple语句)。在上述信息的反馈中,导致ICC model失效的原因可能是反编译工具不同导致差异,使得比如指令位置位移不同等问题。解决方法是先运行FlowDroid导出反编译结果,然后输入到IC3生成ICC model,最后再将ICC model输入到FlowDroid。
最终可以获得ICC model,但IC3在真实应用上的表现很不好,不足以支撑分析需要。
方案二:ICCBot结果转换为ICCmodel
IC3工具在应对真实应用时存在明显不足,故采取其他更有效提取ICC的工具,再将工具结果转换为与IC3格式相同的ICC model,这里采用ICCBot。
这里分为两步:
- step1: 分析ICC model各字段含义
- step2: 从ICCBot中提取ICC结果,转换为与IC3格式相同的ICC model
问题及解决方案
问题一:ICC model 各字段含义
name: 应用包名,manifest.package
version: 应用版本号,manifest.android:versionCode
used_permissions: 应用所申请的权限, uses-permission.android:name
components{ //组件信息,ICC包在其中
name: 组件名
kind: 组件类型, ACTIVITY等4大组件
exported: true/false 当minSdkVersion或targetSdkVersion为16或者更低时他的默认值是true。如果是17和以上的版本默认值是false。
extras{ //如果组件通过extra传递信息则存在该字段, 在调用getStringExtra的组件中出现。}
Intent_filters{
attributes {
kind: ACTION
value:
}
attributes {
kind: CATEGORY
value:
}
}
exit_points{ //如果有ICC,则存在该字段,显式Intent,隐式Intent不同 }
}
analysis_start:开始分析时间戳
analysis_end:结束分析时间戳
举例
extras字段
以Droid Bench/ActivityCommunICation3.apk为例,代码:
ICC model:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16components {
name: "edu.mit.ICC_componentname_class_constant.InFlowActivity"
...
...
extras {
extra: "DroidBench"
instruction {
statement: "$r3 = virtualinvoke $r2.<android.content.Intent: java.lang.String getStringExtra(java.lang.String)>(\"DroidBench\")"
class_name: "edu.mit.ICC_componentname_class_constant.InFlowActivity"
method: "<edu.mit.ICC_componentname_class_constant.InFlowActivity: void onCreate(android.os.Bundle)>"
id: 5
}
}
}
//“class_name”类里的“method”方法中的“statement”语句调用了getStringExtra,该语句在类中的绝对位置为第5行(id),这个位置与反编译结果有关显式Intent
以Droid Bench/ActivityCommunICation3.apk为例,代码:
ICC model:
1 | components { |
- 隐式Intent
以DroidBench/EventOrdering1.apk为例,代码:
ICC model:
1 | components { |
问题二:从ICCBot中提取ICC model
分析源码,分析FlowDroid对ICC model的实际使用过程,删减ICC model,仅保留必要字段的最小集合。提取ICCBot的生成的ICC信息,转变为缩减版ICC model输入到FlowDroid中。ICC model必要字段包括:
- manifest中的所有组件name值:在ICCTA识别ICC的target component时,是直接在ICC model中,通过匹配conponent name,检查是否存在target component。所以ICC model必须包含注册过的所有组件。
- exit_points中的所有字段:exit_points提供ICC的相关信息,包括发起组件的信息(package,class,ICC 方法的caller),ICC 方法(如startActivity等),目标组件的信息(从Intent中提取的信息,显式Intent提取组件名,隐式Intent提取action,catogory等Intent filter)。