日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

使用FlowDroid生成Android应用程序的函数调用图

發布時間:2025/3/15 Android 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用FlowDroid生成Android应用程序的函数调用图 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

提到Android應用程序靜態分析,就不能不提Flowdroid。該工具是目前使用很廣泛的Android應用程序數據流分析工具。它基于強大的Java分析工具Soot開發,提供了許多有用的功能。具體的介紹和使用幫助可以訪問開發團隊的網站?點這里。

然而有時候我們并不需要使用Flowdroid的全部功能,例如有時候我們只想要一個APK里面的函數調用圖。當然我們可以使用androguard(最近好像又更新了)來生成函數調用圖,或者用APKTool來反匯編APK,然后再自己編程搜索反匯編后的smali文件來生成函數調用圖。但是我認為使用Flowdroid生成的調用圖是比較有說服力的。下面直接放代碼。

  • 整個工程的目錄結構,其中CGGenerator.java用來生成調用圖,CGExporter.java里面封裝了一些把調用圖可視化的函數。除此之外還需要導入4個jar包:gexf4j.jar,?AXMLPrinter2.jar,?stax2-api-3.1.1.jar,?woodstox-core-asl-4.0.6.jar。?

    當然本工程還要導入對Flowdroid原本工程(可以從他們的官方網站上找到下載)的依賴。?

  • CGGenerator.java

package flowdroidcg;import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map;import soot.MethodOrMethodContext; import soot.PackManager; import soot.Scene; import soot.SootMethod; import soot.jimple.infoflow.android.SetupApplication; import soot.jimple.toolkits.callgraph.CallGraph; import soot.jimple.toolkits.callgraph.Targets; import soot.options.Options;public class CGGenerator {//設置android的jar包目錄public final static String jarPath = "/home/liu/Android/Sdk/platforms";//設置要分析的APK文件public final static String apk = "/home/liu/app-release.apk";private static Map<String,Boolean> visited = new HashMap<String,Boolean>();private static CGExporter cge = new CGExporter();public static void main(String[] args){SetupApplication app = new SetupApplication(jarPath, apk);try{//計算APK的入口點,這一步導入的文件是Flowdroid進行污點分析的時候需要的,這里直接新建一個空文件即可app.calculateSourcesSinksEntrypoints("/home/liu/temp/sourcesAndSinks.txt");}catch(Exception e){e.printStackTrace();}soot.G.reset();Options.v().set_src_prec(Options.src_prec_apk);Options.v().set_process_dir(Collections.singletonList(apk));Options.v().set_force_android_jar(jarPath + "/android-21/android.jar");Options.v().set_whole_program(true);Options.v().set_allow_phantom_refs(true);Options.v().set_output_format(Options.output_format_none);Options.v().setPhaseOption("cg.spark verbose:true", "on");Scene.v().loadNecessaryClasses();SootMethod entryPoint = app.getEntryPointCreator().createDummyMain();Options.v().set_main_class(entryPoint.getSignature());Scene.v().setEntryPoints(Collections.singletonList(entryPoint));PackManager.v().runPacks();//獲取函數調用圖CallGraph cg = Scene.v().getCallGraph();//可視化函數調用圖visit(cg,entryPoint);//導出函數調用圖cge.exportMIG("flowdroidCFG.gexf", "/home/liu/temp");}//可視化函數調用圖的函數private static void visit(CallGraph cg,SootMethod m){//在soot中,函數的signature就是由該函數的類名,函數名,參數類型,以及返回值類型組成的字符串String identifier = m.getSignature();//記錄是否已經處理過該點visited.put(m.getSignature(), true);//以函數的signature為label在圖中添加該節點cge.createNode(m.getSignature());//獲取調用該函數的函數Iterator<MethodOrMethodContext> ptargets = new Targets(cg.edgesInto(m));if(ptargets != null){while(ptargets.hasNext()){SootMethod p = (SootMethod) ptargets.next();if(p == null){System.out.println("p is null");}if(!visited.containsKey(p.getSignature())){visit(cg,p);}}}//獲取該函數調用的函數Iterator<MethodOrMethodContext> ctargets = new Targets(cg.edgesOutOf(m));if(ctargets != null){while(ctargets.hasNext()){SootMethod c = (SootMethod) ctargets.next();if(c == null){System.out.println("c is null");}//將被調用的函數加入圖中cge.createNode(c.getSignature());//添加一條指向該被調函數的邊cge.linkNodeByID(identifier, c.getSignature());if(!visited.containsKey(c.getSignature())){//遞歸visit(cg,c);}}}} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • CGExporter
package flowdroidcg;import it.uniroma1.dis.wsngroup.gexf4j.core.EdgeType; import it.uniroma1.dis.wsngroup.gexf4j.core.Gexf; import it.uniroma1.dis.wsngroup.gexf4j.core.Graph; import it.uniroma1.dis.wsngroup.gexf4j.core.Mode; import it.uniroma1.dis.wsngroup.gexf4j.core.Node; import it.uniroma1.dis.wsngroup.gexf4j.core.data.Attribute; import it.uniroma1.dis.wsngroup.gexf4j.core.data.AttributeClass; import it.uniroma1.dis.wsngroup.gexf4j.core.data.AttributeList; import it.uniroma1.dis.wsngroup.gexf4j.core.data.AttributeType; import it.uniroma1.dis.wsngroup.gexf4j.core.impl.GexfImpl; import it.uniroma1.dis.wsngroup.gexf4j.core.impl.StaxGraphWriter; import it.uniroma1.dis.wsngroup.gexf4j.core.impl.data.AttributeListImpl;import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import java.util.List;public class CGExporter {private Gexf gexf;private Graph graph;private Attribute codeArray;private AttributeList attrList;public CGExporter() {this.gexf = new GexfImpl();this.graph = this.gexf.getGraph();this.gexf.getMetadata().setCreator("liu3237").setDescription("App method invoke graph");this.gexf.setVisualization(true);this.graph.setDefaultEdgeType(EdgeType.DIRECTED).setMode(Mode.STATIC);this.attrList = new AttributeListImpl(AttributeClass.NODE);this.graph.getAttributeLists().add(attrList);//可以給每個節點設置一些屬性,這里設置的屬性名是 codeArray,實際上后面沒用到this.codeArray = this.attrList.createAttribute("0", AttributeType.STRING,"codeArray");}public void exportMIG(String graphName, String storeDir) {String outPath = storeDir + "/" + graphName + ".gexf";StaxGraphWriter graphWriter = new StaxGraphWriter();File f = new File(outPath);Writer out;try {out = new FileWriter(f, false);graphWriter.writeToStream(this.gexf, out, "UTF-8");} catch (IOException e) {e.printStackTrace();}}public Node getNodeByID(String Id) {List<Node> nodes = this.graph.getNodes();Node nodeFinded = null;for (Node node : nodes) {String nodeID = node.getId();if (nodeID.equals(Id)) {nodeFinded = node;break;}}return nodeFinded;}public void linkNodeByID(String sourceID, String targetID) {Node sourceNode = this.getNodeByID(sourceID);Node targetNode = this.getNodeByID(targetID);if (sourceNode.equals(targetNode)) {return;}if (!sourceNode.hasEdgeTo(targetID)) {String edgeID = sourceID + "-->" + targetID;sourceNode.connectTo(edgeID, "", EdgeType.DIRECTED, targetNode);}}public void createNode(String m) {String id = m;String codes = "";if (getNodeByID(id) != null) {return;}Node node = this.graph.createNode(id);node.setLabel(id).getAttributeValues().addValue(this.codeArray, codes);node.setSize(20);} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 生成的可視化的函數調用圖?
    最后生成的調用圖被保存成了gexf格式,這個格式在網絡分析里面用的比較多。可以用軟件Gephi打開生成的調用圖。

生成的函數調用圖,密密麻麻的全是節點。?

還可以縮放,查看節點label,修改節點顏色等。?

  • 后記?
    FlowDroid比較強大,我自己也沒搞太明白…………Soot里面有可以把調用圖導出成dot格式的函數,但是節點比較多的時候我的電腦打不開那個dot文件了。可能是本人電腦比較渣吧。其實大部分時候獲得了函數調用圖就可以在上面進行分析了,沒必要把它導出來。導出來只是為了人看著方便。
原文地址:?http://blog.csdn.net/liu3237/article/details/48827523

總結

以上是生活随笔為你收集整理的使用FlowDroid生成Android应用程序的函数调用图的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。