0%

[soot]如何反编译类文件

序言

江山留胜迹,我辈复登临。

今天继续跟Soot,来看如何反汇编class文件。

Soot基本用途

Soot有两个基本用途:它可以用作独立的命令行工具或Java编译器框架。

作为命令行工具,Soot可以:

  • 反汇编类文件
  • 汇编类文件
  • 优化类文件

作为Java编译器框架,Soot可用作开发新优化的测试平台。然后,可以将这些新的优化添加到Soot命令行工具调用的优化基础集。添加的优化部分可以应用于单个类文件,也可以应用于整个应用程序。

Soot通过能够以各种不同形式处理类文件来完成这些无数的任务。目前,Soot接受来自以下来源的代码,并输出其任何中间表示:

  • Java(字节码和Java 7之前的源代码),包括编译成Java字节码的其他语言,例如Scala
  • Android字节码
  • 简单的中间表示
  • Jasmin,低级别的中间表示。

通过使用-help选项调用Soot,可以看到输出格式:

image-20200719155822000

Soot中目前使用六个中间表示形式:baf,jimple,shimple,grimp,jasmin和classfile。每种形式的简要说明如下:

  • baf 字节码的简化表示形式。用于检查Java字节码作为堆栈代码,但格式更好。有两种文本表示形式(一种缩写(.b文件),一种完整(.baf文件)。)
  • jimple 键入3地址代码。用于执行优化和检查字节码的非常方便的表示形式。有两个文本表示形式(.jimp文件和.jimple文件。)
  • shimple Jimple的SSA变体。有两个文本表示形式(.shimp文件和.shimple文件。)
  • grimp 聚集的(相对于表达式树)jimple。检查反汇编代码的最佳中间表示。有两个文本表示形式(.grimp文件和.grimple文件。)
  • jasmin 凌乱的汇编器格式。主要用于调试Soot。Jasmin文件以“ .jasmin”结尾。
  • classfiles 原始Java字节码格式。二进制(非文本)表示形式。通常的.class文件。

生成一个Jimple文件

先实现一个简单的Jimple类:

1
2
3
4
5
6
7
public class Hello
{
public static void main(String[] args)
{
System.out.println("Hello world!");
}
}

只需编译该类(使用javac或其他编译器),然后在Hello.class所在的目录中尝试以下命令。

1
java soot.Main -cp CLASSPATH -f jimple Hello
1
java -cp soot-4.2.1.jar soot.Main -cp . -f J -pp Hello

名为Hello.jimple的文件应包含:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Hello extends java.lang.Object
{
public void <init>()
{
Hello r0;

r0 := @this: Hello;
specialinvoke r0.<java.lang.Object: void <init>()>();
return;
}

public static void main(java.lang.String[])
{
java.lang.String[] r0;
java.io.PrintStream $r1;

r0 := @parameter0: java.lang.String[];
$r1 = <java.lang.System: java.io.PrintStream out>;
virtualinvoke $r1.<java.io.PrintStream: void println(java.lang.String)>("Hello world!");
return;
}
}

例子:为Java基础类库生成baf文件

接下来尝试为任何类文件生成.b,.baf,.jimp,.jimple,.grimp和.grimple文件。一个特别好的测试是JDK库中的类文件。所以像这样的命令:

1
java -cp soot-4.2.1.jar soot.Main -cp . -f baf -pp java.lang.String

应该会产生一个文件java.lang.String.baf,其中包含以下格式的文本:

image-20200719163210595

输出java文件

Soot不仅可以产生.jimple文件还可以产生.java文件。如果–f dava用于反编译为Java,请确保该文件/lib/jce.jar位于Soot的类路径中。

举例:

1
java -cp soot-4.2.1.jar soot.Main -cp . -f d  -pp lll

该文件下有一个lll.class文件,直接选择-f d,将其变为java文件:

image-20200719163643401

lll.java代码如下:

image-20200719163715708