0%

FlowDroid 工具介绍和试用(草稿)

工具介绍

FlowDroid[1,2] 是 Arzt 等人设计的一款上下文敏感(对象敏感),流敏感,域敏感的静态污点分析工具,除此之外,与其他污点分析工具(如TAJ)不同的是其针对安卓应用,对安卓应用的特性做了很多改进和优化。

该工具基于Soot[3]和Heros[4],soot作为经典的Java语言分析框架,能提供SSA和callgraph,Heros是一个通用的IFDS/IDS分析框架,速度没有WALA快,但是比WALA更通用。

aliasFlow

FlowDroid 在污点分析时参考了[Andromeda][http://www.cs.tau.ac.il/~omertrip/fase13/paper.pdf]的做法,有一定的别名分析,具体来说,当污点被load至一个堆区(如图中`x.f=w`)时,进行反向分析,污染别名变量(如图中的z.g.f, a.g.f),再检查污点是否进入sink(如图中b.f),具体算法后文会做分析。

使用

构建工具

1
2
3
4
git checkout v2.8 # 先切换到稳定版本
export ANDROID_JARS=/mnt/d/java_lib/Android/android-sdk/platforms
export DROIDBENCH=/mnt/d/PA/FlowDroid/DroidBench
mvn -DskipTests install

注意:v2.8分支依赖的soot版本是4.3.0-SNAPSHOT,而github的soot仓库最高版本还是4.2.1,因此这里我手动改一下,希望不要出事Orz

使用

1
java -jar soot-infoflow-cmd/target/soot-infoflow-cmd-jar-with-dependencies.jar -a DroidBench/apk/GeneralJava/Clone1.apk -p $ANDROID_JARS -s soot-infoflow-android/SourcesAndSinks.txt

有如下结果

1
2
3
4
5
6
7
8
9
10
$ java -jar soot-infoflow-cmd/target/soot-infoflow-cmd-jar-with-dependencies.jar -a DroidBench/apk/GeneralJava/Loop1.apk -p $ANDROID_JARS -s soot-infoflow-android/SourcesAndSinks.txt
[main] INFO soot.jimple.infoflow.cmd.MainClass - Analyzing app /mnt/d/program-analysis/FlowDroid/DroidBench/apk/GeneralJava/Loop1.apk (1 of 1)...
[main] INFO soot.jimple.infoflow.android.SetupApplication - Initializing Soot...
[main] INFO soot.jimple.infoflow.android.SetupApplication - Loading dex files...
[main] INFO soot.jimple.infoflow.android.SetupApplication - ARSC file parsing took 0.0135045 seconds
# ...
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - The sink virtualinvoke $r7.<android.telephony.SmsManager: void sendTextMessage(java.lang.String,java.lang.String,java.lang.String,android.app.PendingIntent,android.app.PendingIntent)>("+49 1234", null, r5, null, null) in method <de.ecspride.LoopExample1: void onCreate(android.os.Bundle)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - - $r4 = virtualinvoke r3.<android.telephony.TelephonyManager: java.lang.String getDeviceId()>() in method <de.ecspride.LoopExample1: void onCreate(android.os.Bundle)>
[main] INFO soot.jimple.infoflow.android.SetupApplication$InPlaceInfoflow - Data flow solver took 0 seconds. Maximum memory consumption: 53 MB
[main] INFO soot.jimple.infoflow.android.SetupApplication - Found 1 leaks

源码解析

首先FlowDroid项目有四个子项目:

  • soot-infoflow: 数据流分析核心包(基于Soot)
  • soot-infoflowandroid: 与安卓特性相关的数据流分析
  • soot-infoflow-summaries:还不清楚,像是做函数摘要的类
  • soot-infoflow-cmd:命令行入口

soot.jimple.infoflow.cmd.MainClass#main

先从入口开始,程序入口在soot-infoflow-cmd包下面的soot.jimple.infoflow.cmd.MainClass,主要通过命令传入一些配置,包括但不限于:

  • -apkfile:apk文件
  • -platformsdir:Android SDK
  • -platformsdir: Source & Sink定义
  • -outputfile:输出文件
  • -timeout:数据流分析超时时间
  • -callbacktimeout:callback收集超时时间

与特性、算法相关:

  • -nostatic:不分析静态数据流
  • -nocallbacks:不分析callback
  • -noexceptions:不分析exception数据流
  • -notypechecking:不分析污点类型检查
  • -enablereflection:允许反射特性
  • -missingsummariesoutputfile:列出函数摘要缺失的类
  • -outputlinenumbers:列出bytecode line number
  • -taintwrapper:【TODO】这个不是很清楚,可以设置None,EASY,STUBDROID或BULTI
  • -taintwrapperfile:设置污点文件
  • -aplength:路径最大长度
  • -cgalgo:调用图生成算法,e.g. CHA,VTA,RTA,SPARK, GEOM
  • -pathalgo:返回结果算法,e.g., CONTEXTSENSITIVE, CONTEXTINSENSITIVE, SOURCESONLY
  • -dataflowsolver:数据流解析算法, e.g., CONTEXTFLOWSENSITIVE, FLOWINSENSITIVE

还有很多配置等用到时再分析。

接着设置ITaintPropagationWrapper,该接口用于使用函数摘要传播污点,主要用于加速分析以及对抗源代码不存在以及native的情况

1
2
3
// Initialize the taint wrapper. We only do this once for all apps to cache
// summaries that we have already loaded.
ITaintPropagationWrapper taintWrapper = initializeTaintWrapper(cmd);

接着根据配置产生一个analyzer(SetupApplication,继承自ITaintWrapperDataFlowAnalysis);

1
2
3
// Create the data flow analyzer
analyzer = createFlowDroidInstance(config);
analyzer.setTaintWrapper(taintWrapper);

最后调用analyzer.runInfoflow()启动分析主流程。

1
2
// Start the data flow analysis
analyzer.runInfoflow();

soot.jimple.infoflow.android.SetupApplication#runInfoflow()

现在进入了soot-infoflow-android包,在runInfoflow()中,先调用ISourceSinkDefinitionProvider读取source-sink文件,文件可以有三种格式:xml, txt和rifl,接着调用SetupApplication.runInfoflow(ISourceSinkDefinitionProvider):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public InfoflowResults runInfoflow() throws IOException, XmlPullParserException {
// If we don't have a source/sink file by now, we cannot run the data
// flow analysis
// ...
ISourceSinkDefinitionProvider parser = null;
try {
if (fileExtension.equals(".xml")) {
parser = XMLSourceSinkParser.fromFile(sourceSinkFile,
new ConfigurationBasedCategoryFilter(config.getSourceSinkConfig()));
} else if (fileExtension.equals(".txt"))
parser = PermissionMethodParser.fromFile(sourceSinkFile);
else if (fileExtension.equals(".rifl"))
parser = new RIFLSourceSinkDefinitionProvider(sourceSinkFile);
else
throw new UnsupportedSourceSinkFormatException("The Inputfile isn't a .txt or .xml file.");
} catch (SAXException ex) {
throw new IOException("Could not read XML file", ex);
}

return runInfoflow(parser);
}

在 SetupApplication.runInfoflow(ISourceSinkDefinitionProvider)中,首先初始化Soot——initializeSoot(),包括制定指针分析方法(默认SPARK)、给一些特定调用添加CallGraph边——LibraryClassPatcher.patchLibraries();接着读取Android资源和配置文件,包括AndroidManifest.xml文件,这些文件用于获取分析入口;接着对entrypoint进行分析——SetupApplication.processEntryPoint;最后收集分析结果并返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public InfoflowResults runInfoflow(ISourceSinkDefinitionProvider sourcesAndSinks) {
// Start a new Soot instance
G.reset();
initializeSoot();

// Perform basic app parsing
parseAppResources();

MultiRunResultAggregator resultAggregator = new MultiRunResultAggregator();

// In one-component-at-a-time, we do not have a single entry point
// creator. For every entry point, run the data flow analysis.
processEntryPoint(sourcesAndSinks, resultAggregator, -1, null);

// Write the results to disk if requested
serializeResults(resultAggregator.getAggregatedResults(), resultAggregator.getLastICFG());

// We return the aggregated results
this.infoflow = null;
resultAggregator.clearLastResults();
return resultAggregator.getAggregatedResults();
}

soot.jimple.infoflow.Infoflow#runAnalysis(ISourceSinkManager, Set\)

Reference

  1. https://blogs.uni-paderborn.de/sse/tools/flowdroid/
  2. https://github.com/secure-software-engineering/FlowDroid
  3. https://github.com/soot-oss/soot
  4. http://sable.github.io/heros/