soot简介及安装运行

soot官方文档: https://github.com/Sable/soot/wiki

一. soot简介
1. 概念
Originally, Soot started off as a Java optimization framework. By now, researchers and practitioners from around the world use Soot to analyze, instrument, optimize and visualize Java and Android applications.

soot是java优化框架,提供4种中间代码来分析和转换字节码。

Baf:精简的字节码表示,操作简单
Jimple:适用于优化的3-address中间表示
Shimple:Jimple的SSA变体
Grimple:适用于反编译和代码检查的Jimple汇总版本。
2. soot提供的输入输出格式
输入格式:
- java(bytecode and source code up to Java 7)
- anroid 字节码
- Jimple中间表示
- Jasmin,低级中间表示
- soot提供的分析功能
输出格式:
- java 字节码
- android字节码
- Jimple
- Jasmin
提示:计算机上的java环境最好是1.7版本,否则运行容易出错。
3. soot提供的分析功能
- 调用图构造
- 指针分析
- Def/use chains
- 模板驱动的程序内数据流分析
- 模板驱动的程序间数据流分析,与heros结合
- 结合FlowDroid的污染分析

二. 安装
https://www.sable.mcgill.ca/soot/soot_download.html中下载soot.jar

三. 使用
soot.jar下载好后,使用命令行来运行soot:

java -jar soot.jar

soot的使用方法一般有两种。一种为用命令行使用soot,另一种为java程序中使用soot。
1.命令行使用
(1) 处理单个文件
soot可以处理三种类型的文件:java源代码(。java文件),java字节码(.class文件),Jimple源代码(.jimple文件)
Jimple是soot中最主要的中间表示,三地址代码基本上是一种Java的简化版本,只需要大约15种不同的指令。

java -jar soot.jar A B

其中,A B叫做应用类。如果只运行该命令,可能报错,因为soot有自己的classpath,它只会从该路径的jar文件或目录加载文件。所有要用-cp指出路径。
但运行之后还可能会报错,因为soot需要知道类型信息,它需要为局部变量重构类型,那么它要知道你 要处理的文件的完整类层次。有三种方法可以解决。
a.添加相关的jar文件到classpath,比如说JDK的rt.jar。
b.使用-pp选项。-pp表示prepend path,它表示Soot自动将以下内容添加到类路径中(按此顺序):当前环境的CLASSPATH变量值;{JAVA_HOME}/lib/rt.jar;如果使用-w(whole-program mode),添加{JAVA_HOME}/lib/jce.jar。
c. 使用-allow-phantom-refs。如果soot无解析类型,它会创建一个phantom类。这种方法非常有限,在很多情况下不会得到您需要的结果。
(2)处理整个文件夹

java -jar soot.jar -process-dir 文件名

如果要处理jar文件,也是使用-process-dir 选项,后跟jar文件路径。同时可以使用-d选项,对soot的输出重定向。
(3)处理确定类型的文件
假设你有个文件夹下放了A.java和A.class文件,并且你之前运行过soot,soot会自行加载A.class中A的定义。可能这并不是你想要的,那么可以使用-src-prec选项指定你想要处理的文件类型。-src-prec有4个值可供使用:

  • c或class(默认)
  • only-class:只使用class文件作为soot的源。
  • J或jimple
  • java

比如: -src-prec java 只加载A.java
(4)应用类和库类
soot处理的类就叫做应用类,但库类恰恰相反,soot并不处理,只是用来类型分析。
(5)指定输出类型
使用-f选项,指定你想要soot为你生成的文件类型,比如.jimple文件,.class文件,甚至.java文件。
(6)阶段选项
soot支持不同细粒度的选项,允许您直接从命令行调整所有满足您的要求的分析和优化。这些命令选项的一般格式是-p PHASE OPT:VAL。所有阶段选项的完整文档:http://www.sable.mcgill.ca/soot/tutorial/phase/
例如,我们想要在soot执行过程中保留局部变量名。那么就在命令行里添加选项-p jb ues-original-names:true

2.编写java程序使用
soot的java api文档:https://soot-build.cs.uni-paderborn.de/public/origin/develop/soot/soot-develop/jdoc/
如果我们想要编写一个java程序来访问一个Class中的所有Field和Methods,那么用java语言编写使用soot API,应该怎么做呢?
首先要指定classpath,然后像在命令行里添加选项一样对选项进行设置(比如对-process-dir设置)。其次将你想要的应用类加载到soot环境中Scene。然后对soot环境中的每个class进行遍历,再对每个class中的每个method方法访问。
假如我要对Employee.java文件中的字段和方法进行访问。

Employee.java:

import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Objects;

public class Employee {
    private String name;
       private double salary;
       private Date hireDay;

       public Employee(String n, double s, int year, int month, int day)
       {
          name = n;
          salary = s;
          GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
          hireDay = calendar.getTime();
       }

       public String getName()
       {
          return name;
       }

       public double getSalary()
       {
          return salary;
       }

       public Date getHireDay()
       {
          return hireDay;
       }

       public void raiseSalary(double byPercent)
       {
          double raise = salary * byPercent / 100;
          salary += raise;
       }

       public boolean equals(Object otherObject)
       {
          // a quick test to see if the objects are identical
          if (this == otherObject) return true;

          // must return false if the explicit parameter is null
          if (otherObject == null) return false;

          // if the classes don't match, they can't be equal
          if (getClass() != otherObject.getClass()) return false;

          // now we know otherObject is a non-null Employee
          Employee other = (Employee) otherObject;

          // test whether the fields have identical values
          return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);
       }

       public int hashCode()
       {
          return Objects.hash(name, salary, hireDay); 
       }

       public String toString()
       {
          return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay
                + "]";
       }
}

helloSoot.java:

import java.io.File;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.*;

import soot.Scene;
import soot.SootClass;
import soot.SootMethod;
import soot.SourceLocator;
import soot.options.Options;

public class helloSoot {
    private String apiPath = "/home/myw/name";

    public void getClassUnderDir() {
        apiClasses = new LinkedHashSet<String>();
        for (String clzName: SourceLocator.v().getClassesUnder(apiPath)) {
            System.out.printf("api class: %s\n", clzName);
            //加载要处理的类设置为应用类,并加载到soot环境Scene中  
            Scene.v().loadClass(clzName, SootClass.BODIES).setApplicationClass();
        }
    }

    public void getMethods() {
        for (SootClass clz : Scene.v().getApplicationClasses()) {
            System.out.println(clz.getName());
            if (clz.getMethods().size() == 0){System.out.println("do not have methods!!!!!");}
            else{
                System.out.println("method num:"+clz.getMethods().size());
                for(SootMethod me : clz.getMethods()) {
                    System.out.println(me.toString());
                    if (me.hasActiveBody()){
                        System.out.println(me.getActiveBody().toString());
                    }
                }
            }

        }

    }

    private static void setOptions() {
         soot.options.Options.v().set_keep_line_number(true);
         soot.options.Options.v().set_whole_program(true);
       // LWG
         soot.options.Options.v().setPhaseOption("jb", "use-original-names:true");
         soot.options.Options.v().setPhaseOption("cg", "verbose:false");
         soot.options.Options.v().setPhaseOption("cg", "trim-clinit:true");
         //soot.options.Options.v().setPhaseOption("jb.tr", "ignore-wrong-staticness:true");

         soot.options.Options.v().set_src_prec(Options.src_prec_java);
         soot.options.Options.v().set_prepend_classpath(true);

         // don't optimize the program 
         soot.options.Options.v().setPhaseOption("wjop", "enabled:false");
         // allow for the absence of some classes
         //soot.options.Options.v().set_allow_phantom_refs(true);

    }

    private static void setSootClassPath() {
        StringBuffer cp = new StringBuffer();
        cp.append(".");
        cp.append(File.pathSeparator + "/home/myw/name");

    cp.append(File.pathSeparator+"/usr/lib/jvm/jdk1.7.0_79/jre/lib/rt.jar"+File.pathSeparator+"/usr/lib/jvm/jdk1.7.0_79/jre/lib/jce.jar");
        System.setProperty("soot.class.path", cp.toString());
    }

    public static void main(String[] args) {
        setSootClassPath();//设置classpath
        setOptions();//设置soot的选项

        helloSoot s = new helloSoot();
        s.getClassUnderDir();
        s.getMethods();
    }
}
  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值