Soot 是一个分析和转换 Java 以及 Android 应用程序的框架,目前已支持 Java 9
Github 、MavenRepo、Paderborn大学源
提供了四种中间表示
Baf | Jimple | Shimple | Grimp |
---|---|---|---|
易于操作的字节码简化形式 | 适用于优化的三地址码形的中间表示 | Jimple 的SSA变体 | 适用于反编译和代码检查的 Simple 整合版 |
如何开始使用 Soot ?
Soot 的 wiki、教程 以及 JavaDoc文档和命令行选项的参考
本文使用的是 Soot 4.2.1(当前最新)
java -cp soot-4.2.1-jar-with-dependencies.jar soot.Main
Soot version trunk
Copyright (C) 1997-2010 Raja Vallee-Rai and others.
All rights reserved.
...
java -cp soot-4.2.1-jar-with-dependencies.jar soot.Main --help
General Options:
-coffi Use the good old Coffi front end for parsing
Java bytecode (instead of using ASM).
-jasmin-backend Use the Jasmin back end for generating Java
bytecode (instead of using ASM).
-h, -help Display help and exit
-pl, -phase-list Print list of available phases
-ph ARG -phase-help ARG Print help for specified ARG
-version Display version information and exit
-v, -verbose Verbose mode
...
通常 Soot 会处理很多类,格式如下:
- Java 源文件,即 .java 文件
- Java 字节码,即 .class 文件
- Jimple 源文件,即 .jimple 文件
Simple 是 Soot 的主要中间表示,它是一个三地址码,可以说是 Java 的一种简化版本,只有大约15种不同类型的语句。可以用 Soot 将 .java 或 .class 文件转换为 .jimple 文件,反之亦然。甚至可以先用 .java 生成 .jimple,手动优化修改后,再将其转换为 .class。
因为是 JDK8,需要先编译 Java文件,然后才能将其作为命令行参数进行传递
java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~18.04-b09)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)
java -cp soot-4.2.1-jar-with-dependencies.jar soot.Main A
Soot started on Mon Nov 16 19:20:56 CST 2020
soot.SootResolver$SootClassNotFoundException: couldn't find class: A (is your soot-class-path set properly?)
...
Soot 有自己的类路径,只会从该路径上的 JAR 文件或目录加载文件!然而此路径默认为空,因此在上面示例种,尽管存在 .class,但 Soot 看不到。
java -cp soot-4.2.1-jar-with-dependencies.jar soot.Main -cp . A
Soot started on Mon Nov 16 19:41:45 CST 2020
java.lang.RuntimeException: None of the basic classes could be loaded! Check your Soot class path!
at soot.Scene.loadBasicClasses(Scene.java:1755)
at soot.Scene.loadNecessaryClasses(Scene.java:1845)
at soot.Main.run(Main.java:241)
at soot.Main.main(Main.java:141)
Soot 需要 java.lang.Object,为了对程序进一步处理,Soot 需要知道类型信息,特别是它需要重新构造局部变量的类型。为此,它需要知道所处理的类的完整类型层次。三种解决办法:
- 将 rt.jar 加入类路径
- 如果使 CLASSPATH 变量包含 rt.jar 或 JAVA_HOME,添加 -pp选项(本文采用)
- 使用 -allow-phantom-refs 选项(不推荐)
-pp 即 -prepend-classpath,表示 Prepend the given soot classpath to the default classpath.
java -cp soot-4.2.1-jar-with-dependencies.jar soot.Main -cp . -pp A
Soot started on Mon Nov 16 20:05:12 CST 2020
Soot finished on Mon Nov 16 20:05:13 CST 2020
Soot has run for 0 min. 0 sec.
最终将在路径下生成 sootOutput\A.class。
此外还可以使用 –process-dir 选项处理整个目录或 JAR 文件,-d 重定向 Soot 的输出位置。
java -cp soot-4.2.1-jar-with-dependencies.jar soot.Main -cp . -pp -process-dir . -d /tmp/sootout
有时我们需要选择输入类型,比如同一目录下有 A.java 和 A.class。-src-prec 能告知 Soot 首选输入。下面是参数:
- c 或 class(默认):
- only-class:
- J 或 jimple:
- java
生成控制流图
使用 Soot 的 soot.tools.CFGViewer 工具分析生成 DOT 语言描述的控制流图,然后用 graphviz 可视化。
java -cp soot-4.2.1-jar-with-dependencies.jar soot.tools.CFGViewer -cp . -pp A
Soot started on Mon Nov 16 20:35:22 CST 2020
Soot finished on Mon Nov 16 20:35:22 CST 2020
Soot has run for 0 min. 0 sec.
sudo apt-get install graphviz
dot -Tpng -o 图片名.png DOT文件名.dot
...