Soot(一)——安装与基本使用
系统:Ubuntu 20.04
使用的Java版本:JDK11与JDK8均可使用,如果解析JAVA源码时出现问题,需要将版本降到JDK7
本系列的目的:
- 总结自己学习的东西,以便日后温习查询之用
- 该工具目前暂时没有中文版本,而soot是Android静态分析的基础,本文填补了这个空白
- 方便学弟学妹学习时少走弯路,中英文对照更好理解
安装
参考资料:https://github.com/soot-oss/soot/wiki/Introduction:-Soot-as-a-command-line-tool
Soot的下载地址:
https://soot-build.cs.uni-paderborn.de/public/origin/master/soot/soot-master/
每一个版本下面都有三个文件夹:build
、jdoc
、options
build
内存放的是Soot的资源文件
options
内存放的是操作文档
一般来说,我们只会使用sootclasses-trunk-jar-with-dependencies.jar
下载完成后,使用java -cp sootclasses-trunk-jar-with-dependencies.jar soot.Main
后,会出现如下提示信息:
Soot version trunk
Copyright (C) 1997-2010 Raja Vallee-Rai and others.
All rights reserved.
Contributions are copyright (C) 1997-2010 by their respective contributors.
See the file 'credits' for a list of contributors.
See individual source files for details.
Soot comes with ABSOLUTELY NO WARRANTY. Soot is free software,
and you are welcome to redistribute it under certain conditions.
See the accompanying file 'COPYING-LESSER.txt' for details.
Visit the Soot website:
http://www.sable.mcgill.ca/soot/
For a list of command line options, enter:
java soot.Main --help
证明下载成功
使用java -cp sootclasses-trunk-jar-with-dependencies.jar soot.Main --help
能获得冗长的帮助信息
这些帮助信息在options
文件夹内有一个HTML版本,看起来更方便
基本使用
为了避免每次都输入一大串的参数,我写了一个很简单的shell脚本辅助使用
#!/bin/bash
SOOT_PATH=/home/yingmanwumen/Documents/soot/sootclasses-trunk-jar-with-dependencies.jar
java -cp $SOOT_PATH soot.Main -cp . -pp $1 $2 $3 $4 $5 $6 $7 $8 $9
使用的时候,把这个脚本放在~/.local/bin
下,然后用chmod
命令赋予权限即可
现在对这个脚本中的两个参数-cp
、-pp
作解释
-cp
在soot.Main --help
的帮助信息中,有这个参数的解释
-cp path
-soot-class-path path
-soot-classpath path
Use path as the classpath for finding classes.
soot下有自己的一个soot class path
,不同于shell
当前路径
使用的时候,需要指定soot class path
需要注意的是,soot class path
中不能有~
符号,即家目录符号,因为该符号是在shell
里面展开的而非是在soot
里面展开的,应该使用完整的路径,例如/home/yingmanwumen
这种的
-pp
-pp
-prepend-classpath
Prepend the given soot classpath to the default classpath.
soot要进行汇编、反汇编等等工作,需要解析必要的符号类型
这个工作不由soot完成,因此,soot的soot class path
中需要jdk中对应的jar包,linux下使用:
分隔多个地址
另一个简便的方式就是使用-pp
参数,自动包含所需的jar
包地址
本着简便易用的原则,不在此处介绍其他方式
输入
可以将多个文件并排输入,也可以使用-process-dir
一次输入一个文件夹
例如文件目录下有
HelloWorld.java
HelloWorld.class
可以使用java -cp soot.jar soot.Main -cp . -pp HelloWorld
进行解析
也可以使用java -cp soot.jar soot.Main -cp . -pp -process-dir .
进行解析
Soot支持多种格式的输入
-src-prec format
c class
only-class
J jimple
java
apk
apk-class-jimple apk-c-j
默认解析.class
文件
例如,在上面的例子中,若需要解析.java
文件,则只需指定-src-prec java
即可
此处,soot有一个bug,当java文件内有IO操作时,无法进行解析
解决办法是,将JDK版本降到JDK7
输出
使用-d
参数指定输出文件夹
因为Soot的默认输出文件夹是./sootOutput
,在重复使用-process-dir
指令的时候,会将./sootOutput
的内容一并解析,因此,可以使用-d
来指定输出的文件夹
使用-f
参数来指定解析结果的输出格式
-f format
-output-format format
J jimple
j jimp
S shimple
s shimp
B baf
b
G grimple
g grimp
X xml
dex
force-dex
n none
jasmin
c class
d dava
t template
a asm
其中,jimple
、jimp
、shimple
、shimp
、baf
、grimple
、grimp
都是soot支持的IR(中间文件)
以hello world
程序为例
public class Helloworld {
public static void main(String[] args) {
System.out.println("Hello, world");
}
}
以jimple
格式输出,如下
public class Helloworld extends java.lang.Object
{
public void <init>()
{
Helloworld r0;
r0 := @this: Helloworld;
specialinvoke r0.<java.lang.Object: void <init>()>();
return;
}
public static void main(java.lang.String[])
{
java.io.PrintStream $r0;
java.lang.String[] r1;
r1 := @parameter0: java.lang.String[];
$r0 = <java.lang.System: java.io.PrintStream out>;
virtualinvoke $r0.<java.io.PrintStream: void println(java.lang.String)>("Hello, world");
return;
}
}
至于Jimple的具体语法,将在以后的系列中进行讲解