一、Soot的安裝與使用
1、soot簡介
Soot是McGill大學的Sable研究小組自1996年開始開發的Java字節碼分析工具,它提供了多種字節碼分析和變換功能,通過它可以進行過程內和過程間的分析優化,以及程序流圖的生成,還能通過圖形化的方式輸出,讓用戶對程序有個直觀的了解。尤其是做單元測試的時候,可以很方便的通過這個生成控制流圖然后進行測試用例的覆蓋,顯著提高效率。
soot項目在github上的地址為:https://github.com/Sable/soot
soot是java優化框架,提供4種中間代碼來分析和轉換字節碼。
- Baf:精簡的字節碼表示,操作簡單
- Jimple:適用於優化的3-address中間表示
- Shimple:Jimple的SSA變體
- Grimple:適用於反編譯和代碼檢查的Jimple匯總版本。
soot提供的輸入和輸出格式
輸入格式
- java
- android 字節碼
- Jasmin,低級中間表示
- soot提供的分析功能
- class(Java8以后)
輸出格式
- Java字節碼
- android字節碼
- Jimple
- Jasmin
- shimple
- baf
- grimple
- xml
- class
- dava
- template
- jar文件
soot提供的分析功能
- 調用圖構造
- 指針分析
- Def/use chains
- 模塊驅動的程序內數據流分析
- 結合FlowDroid的污染分析
2.soot的安裝
目前來說,要使用soot有三種途徑,分別是命令行、程序內以及Eclipse插件(不推薦)
2.1、命令行
可以在這里下載最新的soot jar包,我下載的是4.1.0版本中的sootclasses-trunk-jar-with-dependencies.jar 包,這個包應該自帶了soot所需要的所有依賴。下載完成后使用powershell進入jar文件所在的文件夾(我的是D:\programing\sootTest),輸入以下命令:
java -cp sootclasses-trunk-jar-with-dependencies.jar soot.Main
可以看到:
再輸入
java -cp sootclasses-trunk-jar-with-dependencies.jar soot.Main -h
可以看到有關soot的各種幫助信息。
2.2、程序內使用soot
從github上soot項目的簡介可知,soot一般配合maven來進行部署,相關的依賴添加語句如下:
<dependencies>
<dependency>
<groupId>ca.mcgill.sable</groupId>
<artifactId>soot</artifactId>
<version>4.1.0</version>
</dependency>
</dependencies>
因為目前我的目的只是簡單的使用soot,所以對於程序中soot的使用在后面學習了相關api再來更新。
3.命令行中soot的使用
我的目標是將java轉化為Jimple以發現程序編譯中的問題和規律。因此本文的重點就在這里,我先在soot.jar所在的文件夾下新建了一個java文件HelloWorld.java如下圖所示:
//HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("hello");
}
}
因為我使用的Java版本是JDK1.8,根據soot提示,默認輸入是class文件,所以我先用javac命令將HelloWorld.java編譯為HelloWorld.class。
javac HelloWorld.java
下面我們嘗試將上面得到的class文件作為輸入傳給soot.
java -cp sootclasses-trunk-jar-with-dependencies.jar soot.Main -pp -cp . HelloWorld
得到的結果沒有報錯,但是也無事發生,這是因為soot需要通過-f屬性指定輸出的類型,這里我們將輸出類型指定為Jimple,查詢文檔之后得知要添加-f J以確定輸出格式,最終的語句如下:
java -cp sootclasses-trunk-jar-with-dependencies.jar soot.Main -f J -pp -cp . HelloWorld
該命令在jar文件所在目錄下生成了一個sootOutput文件夾,里面有一個HelloWorld.jimple文件,使用Idea編輯器打開這個文件,得到的內容如下,這就是一個最基本的HelloWorld.java文件所形成的jimple碼。
public class HelloWorld extends java.lang.Object
{
public void <init>()
{
HelloWorld r0;
r0 := @this;
specialinvoke r0.<init>();
return;
}
public static void main(java.lang.String[])
{
java.io.PrintStream $r0;
java.lang.String[] r1;
r1 := @parameter0;
$r0 = java.lang.System.out;
$r0.println("hello");
return;
}
}
3.soot命令行相關參數設置
soot/wiki里的命令表格寫的十分清楚和明確,這里我就直接搬運過來,方便以后查閱。
二、Soot生成控制流圖
如果是將Soot當作簡單工具來分析的人,可以直接使用Soot自帶的工具soot.tools.CFGViewer分析類中的每個方法的控制流並生成DOT語言描述的控制流圖,然后用graphviz中的dot命令來轉換成可視化圖形格式如.PNG
1、使用soot.tools.CFGViewer來生成Triangle.class的控制流圖
//Triangle.class
package Soot;
public class Test {
private double num = 5.0;
public double cal(int num, String type){
double temp=0;
if(type == "sum"){
for(int i = 0; i <= num; i++){
temp =temp + i;
}
}
else if(type == "average"){
for(int i = 0; i <= num; i++){
temp = temp + i;
}
temp = temp / (num -1);
}else{
System.out.println("Please enter the right type(sum or average)");
}
return temp;
}
}
java -cp sootclasses-trunk-jar-with-dependencies.jar soot.tools.CFGViewer -pp -cp . Triangle
生成了Triangle.dot 文件
dot -Tpng -o Triangle.png Triangle.dot
生成了png文件。
三、mac下的Graphviz安裝及使用
1、安裝Graphviz
homebrew安裝完畢后運行 brew install graphviz即可
2、例子
-
使用文本編輯器(這里用的是sublime )輸入以下內容:
digraph pic { Hello -> World }
-
保存為pic.dot文件
-
打開終端,切換到dot文件所在目錄,輸入dot pic.dot -T png -o pic.png
-
可以看到在dot文件目錄下生成了一個pic.png文件