一文入门 soot
字数 1690 2025-08-26 22:11:22
Soot 静态分析工具入门指南
1. Soot 简介
Soot 是一个 Java 静态分析框架,主要用于程序分析和优化。它提供了多种中间表示(IR),其中最常用的是 Jimple,一种有类型的三地址码表示形式。
2. 安装与配置
下载地址
Soot 可以从以下地址下载:
https://soot-build.cs.uni-paderborn.de/public/origin/master/soot/soot-master/
验证安装
运行以下命令验证 Soot 是否安装成功:
java -cp sootclasses-trunk-jar-with-dependencies.jar soot.Main Jimple
Maven 依赖
<dependency>
<groupId>org.soot-oss</groupId>
<artifactId>soot</artifactId>
<version>4.2.1</version>
</dependency>
3. 基本使用
示例代码
public class ForLoop {
public static void main(String[] args) {
int x = 0;
for (int i = 0; i < 10; i++){
x = x + 1;
}
}
}
生成 Jimple 代码
java -cp sootclasses-trunk-jar-with-dependencies.jar soot.Main -cp . -pp -process-dir examples/ForLoop/ -f J
参数说明:
-cp .:添加当前路径到 Soot 的 classpath-pp:自动包含所需的 jar 文件(包括 java.lang.Object)-process-dir:指定处理的目录-f J:生成 Jimple 类型的文件(默认输出到 sootOutput 目录)
其他输出格式选项:
S:ShimpleG:Grimple
生成的 Jimple 示例
public class ForLoop extends java.lang.Object {
public void <init>() {
ForLoop r0;
r0 := @this: ForLoop;
specialinvoke r0.<java.lang.Object: void <init>()>();
return;
}
public static void main(java.lang.String[]) {
java.lang.String[] r0;
int i1;
r0 := @parameter0: java.lang.String[];
i1 = 0;
label1:
if i1 >= 10 goto label2;
i1 = i1 + 1;
goto label1;
label2:
return;
}
}
4. Jimple 中间表示
Jimple 特点
- 有类型的三地址码(typed 3-address code)
- 每个语句最多包含一个操作
- 变量以
r开头(如r0) - 临时变量以
$开头(如$r0)
方法调用类型
specialinvoke:调用构造函数、私有方法或父类方法virtualinvoke:调用虚方法(常规实例方法)interfaceinvoke:调用接口方法staticinvoke:调用静态方法
5. 控制流图(CFG)生成
生成 CFG
java -cp sootclasses-trunk-jar-with-dependencies.jar soot.tools.CFGViewer -cp . -pp -process-dir examples/ForLoop/
安装 Graphviz
apt-get install graphviz
sudo apt-get install graphviz graphviz-doc
生成 PNG
dot -Tpng ForLoopMain.dot -o ForLoop.png
6. Soot 处理流程
Soot 的处理流程分为多个阶段(packs),每个阶段由三个字母标识:
-
第一个字母表示输入类型:
s:Shimplej:Jimpleb:Bafg:Grimp
-
第二个字母表示处理类型:
t:用户定义的转换(transformation)o:优化(optimizations)a:属性生成(attribute generation)b:方法体创建(body creation)
-
第三个字母
p表示 pack(处理阶段)
7. 在 Java 项目中使用 Soot
初始化配置
@Before
public void init() {
soot.G.reset(); // 重置 Soot 环境
Options.v().set_src_prec(Options.src_prec_class); // 设置处理文件类型(默认 class)
Options.v().set_process_dir(Arrays.asList("target/classes/com/examples")); // 处理路径
Options.v().set_whole_program(true); // 开启全局模式
Options.v().set_prepend_classpath(true); // 对应命令行的 -pp
Options.v().set_output_format(Options.output_format_jimple); // 输出 Jimple 文件
Scene.v().loadNecessaryClasses(); // 加载所有需要的类
}
运行分析
@Test
public void test() {
PackManager.v().runPacks(); // 运行所有 packs
PackManager.v().writeOutput(); // 输出结果到 sootOutput 目录
}
8. 自定义转换器(Transformer)
实现 BodyTransformer
public class TransformerTest extends BodyTransformer {
@Override
protected void internalTransform(Body body, String s, Map<String, String> map) {
System.out.println(body.getMethod().getName()); // 输出方法名
}
}
使用自定义 Transformer
@Test
public void test() {
PackManager.v().getPack("jtp").add(new Transform("jtp.TT", new TransformerTest()));
for (SootClass appClazz : Scene.v().getApplicationClasses()) {
for (SootMethod method : appClazz.getMethods()) {
Body body = method.retrieveActiveBody();
PackManager.v().getPack("jtp").apply(body);
}
}
}
9. 流分析框架
Soot 提供了流分析框架,可用于实现数据流分析。
实现步骤
-
继承
FlowAnalysis:- 前向分析:
ForwardFlowAnalysis<Unit, FlowSet> - 后向分析:
BackwardFlowAnalysis<Unit, FlowSet>
- 前向分析:
-
实现关键方法:
copy():复制流值(IN 到 OUT 或 OUT 到 IN)merge():合并流值(实现转换函数)flowThrough():流分析的核心逻辑
-
初始化流值:
newInitialFlow():初始化每个基本块的流值entryInitialFlow():初始化入口流值
-
构造函数必须调用
doAnalysis:
super(graph);
super.doAnalysis();
使用分析结果
OurAnalysis analysis = new OurAnalysis(graph);
analysis.getFlowBefore(s); // 获取 Unit s 之前的流值
analysis.getFlowAfter(s); // 获取 Unit s 之后的流值
10. 关键概念
Box 概念
Unit:表示 Jimple 中的语句Local:表示 Jimple 中的本地变量getUseBoxes():获取语句使用的变量getDefBoxes():获取语句定义的变量
应用类获取
Scene.v().getApplicationClasses() // 获取所有应用类
11. 总结
Soot 是一个功能强大的 Java 静态分析框架,通过本指南,您已经学习了:
- Soot 的安装和基本配置
- Jimple 中间表示的生成和理解
- 控制流图的生成和可视化
- Soot 的处理流程和阶段
- 如何在 Java 项目中使用 Soot
- 如何实现自定义转换器
- 如何使用 Soot 的流分析框架
这些基础知识将帮助您开始使用 Soot 进行更复杂的静态分析任务。