FlowDroid工具的构建与运行
今天早上Aaron收到一封郵件,從我的博客聯(lián)系到我,問我如何運行flowdroid,著實感到開心。這是我博客搭建起來之后第一次有人聯(lián)系到我,感覺自己可以做一點事情很開心。本文是以我對該郵件的回復為基礎加以整理,總結了FlowDroid工具的構建和運行的方法。
回復郵件正文
您好。
我是從讀了這篇論文才開始接觸android的,所以對android基礎知識、運行機制乃至環(huán)境搭建認識非常淺薄。
但我確實把flowdroid運行起來了。
參考資料是官方文檔:https://github.com/secure-software-engineering/soot-infoflow-android/wiki
該文檔對flowdroid的構建分為兩節(jié),Obtaining the nightly builds和Building FlowDroid From Source。我都進行了嘗試。前者是使用事先構建好的flowdroid運行所必須的jar包,后者是從源碼層面自行構建。
采用Obtaining the nightly builds方法時我遇到了android SDK某特定版本找不到的錯誤,由于對android了解甚少,再者我想從代碼層面了解flowdroid,因而我直接放棄了這種方式。
Building FlowDroid From Source。首先從google下載android SDK。然后根據(jù)該小節(jié)所說的,把Jasmin、Heros、Soot、soot-infoflow、soot-infoflow-android源碼下載下來放在同一個目錄下。用eclipse導入已有工程,選擇工程的根目錄。
導入后效果如下圖:
然后,你可以在/soot-infoflow-android/test包下找到對droidBench、insecureBank的Junit測試。例如可以嘗試運行soot.jimple.infoflow.android.test.droidBench.CallbackTests.runTestAnonymousClass1()方法來測試flowdroid在droidbench上的運行效果。
但運行會報錯。1是找不到android sdk,2是找不到droidbench所在目錄,3找不到EasyTaintWrapperSource.txt。通過查看soot.jimple.infoflow.android.test.droidBench.JUnitTests.analyzeAPKFile(String, boolean)方法的源碼可以找到我們需要配置兩個環(huán)境變量:ANDROID_JARS和DROIDBENCH。前者是android.jar所在的目錄,該目錄在android sdk下,目錄結構大概是Android/sdk/platforms/android-23/android.jar這樣的。后者是droidbench測試工程集的目錄。我是OS X Yosemite系統(tǒng),在家目錄下的.bash_profile下做相應配置并使之生效。其他系統(tǒng)的環(huán)境變量配置也不難。至于EasyTaintWrapperSource.txt文件,我發(fā)現(xiàn)soot-infoflow項目中存在這個文件,硬拷貝到soot-infoflow-android工程中的,不知道有沒有更好的方法。
至此,我已經(jīng)可以運行flowdroid了。
除了官方給的一些測試集合,也可以用我們自己寫的一些apk來測試flowdroid。例如我將論文里的示例代碼進行了完善,并用flowdroid進行了測試。主體代碼如下:
package com.example.wangdongwei.myapplication;import android.app.Activity; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.telephony.SmsManager; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.EditText;public class LeakageApp extends Activity {private User user = null;@Overrideprotected void onRestart(){super.onRestart();EditText usernameText =(EditText)findViewById(R.id.username);EditText passwordText =(EditText)findViewById(R.id.pwdString);String uname = usernameText.toString();String pwd = passwordText.toString();if(!uname.isEmpty() && !pwd.isEmpty())this.user = new User(uname, pwd);}//Callback method in xml filepublic void sendMessage(View view){if(user == null) return;Password pwd = user.getpwd();String pwdString = pwd.getPassword();String obfPwd = "";//must track primitivesfor(char c : pwdString.toCharArray())obfPwd += c + "_";String message = "User: " +user.getName() + " | PWD: " + obfPwd;SmsManager sms = SmsManager.getDefault();sms.sendTextMessage("+44 020 7321 0905",null, message, null, null);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_leakage_app);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.menu_leakage_app, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// Handle action bar item clicks here. The action bar will// automatically handle clicks on the Home/Up button, so long// as you specify a parent activity in AndroidManifest.xml.int id = item.getItemId();//noinspection SimplifiableIfStatementif (id == R.id.action_settings) {return true;}return super.onOptionsItemSelected(item);} }然后打包成leakageapp.apk,放在/soot-infoflow-android/testAPKs包下。在/soot-infoflow-android/test/soot/jimple/infoflow/android/test/otherAPKs/OtherAPKTests.java中寫了Junit測試方法:
@Test public void runTest3() throws IOException, XmlPullParserException {InfoflowResults res = analyzeAPKFile("testAPKs/leakageapp.apk", false, false, false);Assert.assertNotNull(res);Assert.assertTrue(res.size() > 0); }方法上右鍵->Run As->JUnit Test進行單元測試。結果如下:
[main] INFO soot.jimple.infoflow.entryPointCreators.AndroidEntryPointCreator - Generated main method:public static void dummyMainMethod(java.lang.String[]){java.lang.String[] $r0;int $i0;com.example.wangdongwei.myapplication.LeakageApp $r1;android.os.Bundle $r2;boolean $z0, $z1;android.view.View $r3;$r0 := @parameter0: java.lang.String[];$i0 = 0;label1:if $i0 == 0 goto label8;$r1 = new com.example.wangdongwei.myapplication.LeakageApp;specialinvoke $r1.<com.example.wangdongwei.myapplication.LeakageApp: void <init>()>();if $i0 == 1 goto label8;$r2 = new android.os.Bundle;specialinvoke $r2.<android.os.Bundle: void <init>()>();virtualinvoke $r1.<com.example.wangdongwei.myapplication.LeakageApp: void onCreate(android.os.Bundle)>($r2);$r2 = null;label2:if $i0 == 2 goto label7;label3:if $i0 == 3 goto label4;$z0 = virtualinvoke $r1.<com.example.wangdongwei.myapplication.LeakageApp: boolean onCreateOptionsMenu(android.view.Menu)>(null);label4:if $i0 == 4 goto label5;$z1 = virtualinvoke $r1.<com.example.wangdongwei.myapplication.LeakageApp: boolean onOptionsItemSelected(android.view.MenuItem)>(null);label5:if $i0 == 5 goto label6;$r3 = new android.view.View;specialinvoke $r3.<android.view.View: void <init>(android.content.Context)>($r1);virtualinvoke $r1.<com.example.wangdongwei.myapplication.LeakageApp: void sendMessage(android.view.View)>($r3);$r3 = null;label6:if $i0 == 6 goto label3;label7:if $i0 == 7 goto label2;if $i0 == 8 goto label8;virtualinvoke $r1.<com.example.wangdongwei.myapplication.LeakageApp: void onRestart()>();if $i0 == 9 goto label2;label8:if $i0 == 11 goto label1;return;}[Call Graph] For information on where the call graph may be incomplete, use the verbose option to the cg phase. [Spark] Pointer Assignment Graph in 0.0 seconds. [Spark] Type masks in 0.0 seconds. [Spark] Pointer Graph simplified in 0.0 seconds. [Spark] Propagation in 0.0 seconds. [Spark] Solution found in 0.0 seconds. [main] INFO soot.jimple.infoflow.codeOptimization.InterproceduralConstantValuePropagator - Removing side-effect free methods is disabled [main] INFO soot.jimple.infoflow.Infoflow - Dead code elimination took 0.028132 seconds [main] INFO soot.jimple.infoflow.Infoflow - Callgraph has 112 edges [main] WARN soot.jimple.infoflow.android.InfoflowAndroidConfiguration - Static field tracking is disabled, results may be incomplete [main] WARN soot.jimple.infoflow.android.InfoflowAndroidConfiguration - Using flow-insensitive alias tracking, results may be imprecise [main] INFO soot.jimple.infoflow.android.InfoflowAndroidConfiguration - Implicit flow tracking is NOT enabled [main] INFO soot.jimple.infoflow.android.InfoflowAndroidConfiguration - Exceptional flow tracking is enabled [main] INFO soot.jimple.infoflow.android.InfoflowAndroidConfiguration - Running with a maximum access path length of 5 [main] INFO soot.jimple.infoflow.android.InfoflowAndroidConfiguration - Using path-agnostic result collection [main] INFO soot.jimple.infoflow.android.InfoflowAndroidConfiguration - Recursive access path shortening is enabled [main] INFO soot.jimple.infoflow.Infoflow - Looking for sources and sinks... [main] INFO soot.jimple.infoflow.Infoflow - Source lookup done, found 5 sources and 1 sinks. [main] INFO soot.jimple.infoflow.Infoflow - Taint wrapper hits: 52 [main] INFO soot.jimple.infoflow.Infoflow - Taint wrapper misses: 61 [main] INFO soot.jimple.infoflow.Infoflow - IFDS problem with 452 forward and 30 backward edges solved, processing 1 results... [main] INFO soot.jimple.infoflow.data.pathBuilders.ContextInsensitiveSourceFinder - Obtainted 1 connections between sources and sinks [main] INFO soot.jimple.infoflow.data.pathBuilders.ContextInsensitiveSourceFinder - Building path 1 [main] INFO soot.jimple.infoflow.data.pathBuilders.ContextInsensitiveSourceFinder - Path processing took 0.003869 seconds in total [main] INFO soot.jimple.infoflow.Infoflow - The sink virtualinvoke $r8.<android.telephony.SmsManager: void sendTextMessage(java.lang.String,java.lang.String,java.lang.String,android.app.PendingIntent,android.app.PendingIntent)>("+44 020 7321 0905", null, $r5, null, null) on line 38 in method <com.example.wangdongwei.myapplication.LeakageApp: void sendMessage(android.view.View)> was called with values from the following sources: [main] INFO soot.jimple.infoflow.Infoflow - - $r1 = virtualinvoke $r0.<com.example.wangdongwei.myapplication.LeakageApp: android.view.View findViewById(int)>(2131492871) on line 19 in method <com.example.wangdongwei.myapplication.LeakageApp: void onRestart()> Maximum memory consumption: 526.43924 MB仔細看一下,該結果是說從findViewById到sendTextMessage的source-sink關系使該程序存在taint的風險。
但其實,對于EditText的對象passwordText,直接調用toString是無法得到其文本內(nèi)容的(正確方式應該是passwordText.getText().toString()),所以這算不算是一個誤報呢?這是我沒有搞明白的一個點。
原文地址:http://aaronmoment.cn/run-flowdroid/
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的FlowDroid工具的构建与运行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用FlowDroid生成Android
- 下一篇: Android污点分析工具flowdro