Turker
发布于 2025-06-29 / 97 阅读
2
0

Java安全——调试&反编译

Java安全——调试&反编译

笔者最近在学习Java安全相关内容,但是目前还处于一个探索阶段,于是边学习边完善这份笔记,写得有问题的话还请见谅。同时在学习Java反序列化等内容时,笔者发现网上的教程总是对初学者不太友好,所以在这份笔记里会有比较充分的样例代码和分析,供各位参考。

编辑:实在太长了,分成几篇发布。

一、Java本地调试和远程调试

1.1 本地调试

不同工具当然有不同的调试方式,这里只介绍我常用的IDEA。

1.1.1 下断点

下断点是一个最为基础的功能,你可以在某一行下个断点,也可以右键下一个条件断点Java安全-1.png
下完断点之后,可以查看你下的所有断点,也可以在这个界面下异常断点
Java安全-3.png

1.1.2 对于断点的调试

有三种按键可以调试我们刚刚下的断点:步过,步入和步出,它们的区别如下:

  • 步过:一行一行执行代码,如果当前行有方法调用,不会进行方法内部。
  • 步入:如果当前行有方法调用,会进入方法内部,否则继续下一行执行。(不进入官方类库的方法,想要进入按Alt + Shift + F7)(智能步入可以选择一行里面的哪些方法要进入哪些不进入)
  • 步出:从步入的方法内推出到方法外面,将方法执行完毕。
    Java安全-2.png

1.1.3 运行即时表达式

IDEA提供了计算即时表达式的调试功能,可以使用这个操作在调试过程中计算某个表达式的值,而不用再去打印信息。这个表达式不仅可以是一般变量或参数,也可以是方法,当你的一行代码中调用了几个方法时,就可以通过这种方式查看查看某个方法的返回值。同时你也可以设置变量的值。
Java安全-4.png

1.1.4 查看栈调用

栈调用是一个非常重要的调试信息,通常栈调用的过程就是程序运行时的逻辑顺序,对寻找调用链之类的调试非常重要。
例如log4j2这个漏洞。我们知道其最终会执行一个jndi注入。那我们直接在java原生执行jndi远程方法调用的位置下出一个断点,这样就可以从栈调用里非常简单的看到整个漏洞的利用过程。

Java安全-5.png

1.2 远程调试

多数情况下,我们进行代码审计或者漏洞复现时,都需要把靶机装在虚拟机里,然后对其进行远程调试。
Java安全-6.png
服务端的参数对于不同版本是有区别的,对于JDK 9 或更新版本:

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:32768

对于 JDK 5-8 :

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=32768

对于 JDK 1.4.x:

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=32768

为了确保远程调试可以成功,需要客户端拥有和服务端一样的源码。之后点击debug,看到成功连接的提示消息就可以像在本地一样调试了。

Java安全-7.png

二、Java反编译

2.1 基本概念

  1. .java和.class文件:java是编译型语言,源码文件是.java,编译后的文件是.class(又称为字节码文件),只有编译之后的文件才能被执行。.class是不可读的二进制文件,反编译的一种场景是需要把.class文件反编译为可读的.java文件。
  2. JVM:JVM是Java Virtual Machine(Java虚拟机)的缩写,编译后的.class文件是交由JVM来执行。JAVA是一种跨平台的语言,也是因为JVM帮我们适应了不同操作系统的区别,导致上层的.class文件是通用的。
  3. Jar包:Jar包是指把大量的Java类文件、相关的元数据和资源文件聚合到一个文件,按照特定的命名和存放方式,以zip的形式进行压缩的文件。Jar包本质上就是一个zip压缩文件,可以用常规的解压软件打开。Jar包可以是独立运行的java运行程序,也可以是供其他程序调用的库文件。如果在Jar包内部的Manifest.MF文件中配置Main-Class属性,则该Jar包可以直接通过java -jar test.jar的方式运行。

2.2 Java反编译方法

首先我们认识一下class文件。
Java安全-8.png
最前面的“cafe babe”是属于java字节码的规定特征,只有以这个字符开头的文件才是JVM能识别的正确的字节码文件。后面的“0000”代表JDK的次版本号,“0034”代表JDK的主版本号。编译的class文件只允许运行在大于等于自己版本的JDK环境中,否则会报错,这里引用一张公开流传的关于字节码组成的图片:

Java安全-9.png
感兴趣的话可以详细了解一下这些字节码组成。我们更加关心的是如何反编译这个字节码文件。
首先,IDEA就自带了反编译工具。直接打开一个class文件就可以对其进行反编译了。反编译一个jar包也很简单,只需要把需要反编译的jar包添加为库,就可以直接对其反编译了。反编译之后的jar包是可读性很好的java代码,IDEA会提示此文件属于反编译的class文件,class文件只能查看,不能修改。
但是我们有的时候需要批量反编译,怎么办呢?这里我个人使用Vineflower/vineflower: Modern Java decompiler aiming to be as accurate as possible, with an emphasis on output quality. Fork of the Fernflower decompiler.这个工具。这样就可以获得反编译后的源码了:

java -jar vineflower-1.11.1.jar Test.jar /destdir

之后我们可以新建一个项目,将/BOOT-INF/classes里面的源码放入/src/main/java,静态资源放到src/main/resources/,pom.xml 放到根目录下,lib目录也直接放进/lib,让idea将其添加为库。这样我们就拥有一个反编译后的完整项目了。


评论