FlowDroid安装初体验

本文详细介绍了如何在最新版本的IntelliJ IDEA环境中配置并使用FlowDroid进行Android应用API调用分析,包括下载相关库、设置路径及测试代码的步骤,适合开发者理解应用数据流和API调用路径。
摘要由CSDN通过智能技术生成

文章参考步骤:2020年FlowDroid+IDEA搭建教程

环境

  1. 刚下载的最新版本的IDEA
  2. 下载soot-jar库(soot-4.2.1-jar-with-dependencies)
  3. 到FlowDroid的github网站下载 2.8版本的soot-infoflow-classes和soot-infoflow-android-classes
  4. 下载trove4j-3.0.3库

注意这里直接点开链接下载,对应版本不要搞错,之后有个示例,如果下了最新的FlowDroid可能就不能运行。

导入jar

打开IDEA
我把所有的jar文件放在了项目下面的lib文件夹
示例图
点开库设置
示例图
在这里的库文件处点击加号,选择JAVA,选择到lib文件夹下一个一个加进去

测试代码

参考的博客
(如果是最新的FlowDroid,可以看到删除了部分函数

package cqu.van;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;


import soot.MethodOrMethodContext;
import soot.Scene;
import soot.SootMethod;
import soot.jimple.infoflow.android.SetupApplication;
import soot.jimple.toolkits.callgraph.CallGraph;
import soot.jimple.toolkits.callgraph.Targets;

public class GetAPI {
	//设置android的jar包目录  
	  public final static String androidPlatformPath = "C:\\Users\\van\\AppData\\Local\\Android\\Sdk\\platforms";  
	  //设置要分析的APK文件  
	  public final static String appDirPath = "F:\\Sample\\benapk";  
	  //设置结果输出的路径
	  
	  //public final static String AnaPath = "F:\\Sample\\malapi";  
	  
	  public final static String SenapiPath = "";
	  static Object ob = new Object();

	  private static Map<String,Boolean> visited = new HashMap<String,Boolean>();  
	  private static  Vector<String> file_vec =  new Vector<String>();
	  private static  Vector<String> sen_api =  new Vector<String>();
	 
	  
	  public static void getfile(){
		  File file = new File(appDirPath);
		  File[] tempList = file.listFiles();
		  for (int i = 0; i < tempList.length; i++) {
	            if (tempList[i].isFile()) {
	            	int lenname =tempList[i].getName().length();
	            	if(tempList[i].getName().substring(lenname-4).equals(".apk"))
	            	{
	            		file_vec.addElement(tempList[i].getName());
	            	}
	            	
	            }
		  }
		  
	  }

	  //apk路径,遍历模式(0只给出边,1给出所有路径),输出位置
	  public static void getapi(String appname,int mode,String AnaPath) {
		  SetupApplication app = new SetupApplication(androidPlatformPath,appDirPath+File.separator+appname);       
	      soot.G.reset();  
	      //构造调用图,但是不进行数据流分析
	      app.constructCallgraph();

	      //SootMethod 获取函数调用图
	      SootMethod entryPoint = app.getDummyMainMethod();
	      CallGraph cg = Scene.v().getCallGraph();
	      
	     // System.out.println(apppath.substring(0,apppath.length()-4)+".txt");
	      File oFile = new File(AnaPath+File.separator+appname.substring(0,appname.length()-4)+".txt");
	      //可视化函数调用图 
	      
	      switch (mode) {
		case 0:
			visit(cg,entryPoint,oFile,entryPoint.getSignature()); 
			break;
		case 1:
			visit1(cg,entryPoint,oFile,entryPoint.getSignature()); 
			break;
		
		default:
			break;
		}
	     
	    
	     
	  }
	  
	  private static void visit(CallGraph cg,SootMethod m,File oFile,String pString){  
	      //在soot中,函数的signature就是由该函数的类名,函数名,参数类型,以及返回值类型组成的字符串  
	      String identifier = m.getSignature();  
	      //记录是否已经处理过该点  
	      visited.put(identifier, true); 
	      //以函数的signature为label在图中添加该节点   
	      //获取该函数调用的函数  
	      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");  
	              }  
	              //将被调用的函数加入图中  
	        
	              //添加一条指向该被调函数的边  
	              //pString = pString+"-->"+ c.getSignature();
	              writerow(oFile,delpar(identifier)+"-->"+ delpar(c.getSignature()));
	              if(!visited.containsKey(c.getSignature())){  
	                  //递归  
	                  visit(cg,c,oFile,pString);  
	              } 
	              //writerow(oFile,pString);
	          }  
	      }  
	  }  
	  
	  
	  private static void visit1(CallGraph cg,SootMethod m,File oFile,String pString){  
	      //在soot中,函数的signature就是由该函数的类名,函数名,参数类型,以及返回值类型组成的字符串  
	      String identifier = m.getSignature();  
	      //记录是否已经处理过该点  
	      visited.put(identifier, true); 
	      //以函数的signature为label在图中添加该节点   
	      //获取该函数调用的函数  
	      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");  
	              }  
	              //将被调用的函数加入图中  
	        
	              //添加一条指向该被调函数的边  
	              pString = pString+"-->"+ c.getSignature();
	              //writerow(oFile,delpar(identifier)+"-->"+ delpar(c.getSignature()));
	              if(!visited.containsKey(c.getSignature())){  
	                  //递归  
	                  visit1(cg,c,oFile,pString);  
	              } 
	              writerow(oFile,pString);
	          }  
	      }  
	  }  
	  
	  
	  private static void visit2(CallGraph cg,SootMethod m,File oFile,String pString){  
	      //在soot中,函数的signature就是由该函数的类名,函数名,参数类型,以及返回值类型组成的字符串  
	      String identifier = m.getSignature();  
	      //记录是否已经处理过该点  
	      visited.put(identifier, true); 
	      //以函数的signature为label在图中添加该节点   
	      //获取该函数调用的函数  
	      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");  
	              }  
	              //将被调用的函数加入图中  

	              if(!visited.containsKey(c.getSignature())){  
	                  //递归  
	            	  writerow(oFile,delpar(c.getSignature()));
	                  visit2(cg,c,oFile,pString);  
	              } 
	          }  
	      }  
	  }  
	  

	  
	  
	  private static void writerow (File ofile, String s) {
		  FileWriter fw = null;
		  try {
			fw = new FileWriter(ofile,true);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		  PrintWriter pw = new PrintWriter(fw);
		  pw.println(s);
		  pw.flush();
		  try {
			fw.flush();
			pw.close();
			fw.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
		
	}
	  
	  
	  public static boolean judgesen(String api) 
	  {
		  return true;
	  }
	  public static String delpar(String s) 
	  {
		  int x = s.indexOf('(');
		  int y = s.indexOf(')');
		  String b = s.substring(0,x+1);
		  String e = s.substring(y,s.length());
		  s=b+e;
		  x = s.indexOf(':');
		  String r = s.substring(x+1,s.length()-1);
		  return r;
	  }
	  
	  public static String cutMethod(String s) 
		{
			 int x = s.indexOf(':');
			 String e = s.substring(x+1,s.length()-1);
			 return e;
		}
	  
	  public static void main(String[] args){
		 // System.out.print(delpar("<org.json.JSONObject: java.lang.String getString(java.lang.String)>"));
		  
		  File LOG = new File("F:\\Sample\\benapi\\log.txt");
		  getfile();
//		  for(int i=0;i<file_vec.size();i++) 
//		  {
//			  System.out.println(file_vec.elementAt(i));
//		  }
		  for(int i=0;i<file_vec.size();i++) 
		  {
			  try {
				  getapi(file_vec.elementAt(i),0,"F:\\Sample\\benapi");
				
			} catch (Exception e) {
				// TODO: handle exception
				writerow(LOG, file_vec.elementAt(i));
			}
			  
			  System.out.println(i);
			  //提取api序列
		  }
	  }
	  
	 
}

结果

成功
输出
也可也在命令行中使用FlowDroid
https://github.com/secure-software-engineering/FlowDroid/releases/tag/v2.10
下载:soot-infoflow-cmd-jar-with-dependenciesjar
然后可以使用GitHub主页中的方式测试
示例

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Godams

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值